xref: /freebsd/sys/dev/arcmsr/arcmsr.c (revision 2f7e72bd1c024e1e8274acbe1ce57514fd444583)
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
90285d85f4S黃清隆 ** 1.50.00.05   03/23/2023  Ching Huang     Fixed reading buffer empty length error
91f1c579b1SScott Long ******************************************************************************************
92f1c579b1SScott Long */
934b7ec270SMarius Strobl 
944b7ec270SMarius Strobl #include <sys/cdefs.h>
9522f2616bSXin LI #if 0
9622f2616bSXin LI #define ARCMSR_DEBUG1			1
9722f2616bSXin LI #endif
98f1c579b1SScott Long #include <sys/param.h>
99f1c579b1SScott Long #include <sys/systm.h>
100f1c579b1SScott Long #include <sys/malloc.h>
101f1c579b1SScott Long #include <sys/kernel.h>
102f1c579b1SScott Long #include <sys/bus.h>
103f1c579b1SScott Long #include <sys/queue.h>
104f1c579b1SScott Long #include <sys/stat.h>
105f1c579b1SScott Long #include <sys/devicestat.h>
106f1c579b1SScott Long #include <sys/kthread.h>
107f1c579b1SScott Long #include <sys/module.h>
108f1c579b1SScott Long #include <sys/proc.h>
109f1c579b1SScott Long #include <sys/lock.h>
110f1c579b1SScott Long #include <sys/sysctl.h>
111f1c579b1SScott Long #include <sys/poll.h>
112f1c579b1SScott Long #include <sys/ioccom.h>
113f1c579b1SScott Long #include <vm/vm.h>
114f1c579b1SScott Long #include <vm/vm_param.h>
115f1c579b1SScott Long #include <vm/pmap.h>
116f1c579b1SScott Long 
117f1c579b1SScott Long #include <isa/rtc.h>
118f1c579b1SScott Long 
119f1c579b1SScott Long #include <machine/bus.h>
120f1c579b1SScott Long #include <machine/resource.h>
121f1c579b1SScott Long #include <machine/atomic.h>
122f1c579b1SScott Long #include <sys/conf.h>
123f1c579b1SScott Long #include <sys/rman.h>
124f1c579b1SScott Long 
125f1c579b1SScott Long #include <cam/cam.h>
126f1c579b1SScott Long #include <cam/cam_ccb.h>
127f1c579b1SScott Long #include <cam/cam_sim.h>
128d74001adSXin LI #include <cam/cam_periph.h>
129d74001adSXin LI #include <cam/cam_xpt_periph.h>
130f1c579b1SScott Long #include <cam/cam_xpt_sim.h>
131f1c579b1SScott Long #include <cam/cam_debug.h>
132f1c579b1SScott Long #include <cam/scsi/scsi_all.h>
133f1c579b1SScott Long #include <cam/scsi/scsi_message.h>
134f1c579b1SScott Long /*
135f1c579b1SScott Long **************************************************************************
136f1c579b1SScott Long **************************************************************************
137f1c579b1SScott Long */
138f1c579b1SScott Long #include <sys/selinfo.h>
139f1c579b1SScott Long #include <sys/mutex.h>
140ad6d6297SScott Long #include <sys/endian.h>
141f1c579b1SScott Long #include <dev/pci/pcivar.h>
142f1c579b1SScott Long #include <dev/pci/pcireg.h>
14344f05562SScott Long 
14422f2616bSXin LI #define arcmsr_callout_init(a)	callout_init(a, /*mpsafe*/1);
14522f2616bSXin LI 
146285d85f4S黃清隆 #define ARCMSR_DRIVER_VERSION	"arcmsr version 1.50.00.05 2023-03-23"
147f1c579b1SScott Long #include <dev/arcmsr/arcmsr.h>
148f1c579b1SScott Long /*
149f1c579b1SScott Long **************************************************************************
150f1c579b1SScott Long **************************************************************************
151f1c579b1SScott Long */
15222f2616bSXin LI static void arcmsr_free_srb(struct CommandControlBlock *srb);
153ad6d6297SScott Long static struct CommandControlBlock *arcmsr_get_freesrb(struct AdapterControlBlock *acb);
154ad6d6297SScott Long static u_int8_t arcmsr_seek_cmd2abort(union ccb *abortccb);
155f2aa0e9fSWarner Losh static int arcmsr_probe(device_t dev);
156f2aa0e9fSWarner Losh static int arcmsr_attach(device_t dev);
157f2aa0e9fSWarner Losh static int arcmsr_detach(device_t dev);
158ad6d6297SScott Long static u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t ioctl_cmd, caddr_t arg);
159ad6d6297SScott Long static void arcmsr_iop_parking(struct AdapterControlBlock *acb);
160f2aa0e9fSWarner Losh static int arcmsr_shutdown(device_t dev);
16144f05562SScott Long static void arcmsr_interrupt(struct AdapterControlBlock *acb);
162ad6d6297SScott Long static void arcmsr_polling_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb);
163ad6d6297SScott Long static void arcmsr_free_resource(struct AdapterControlBlock *acb);
164ad6d6297SScott Long static void arcmsr_bus_reset(struct AdapterControlBlock *acb);
165ad6d6297SScott Long static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb);
166ad6d6297SScott Long static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb);
167ad6d6297SScott Long static void arcmsr_iop_init(struct AdapterControlBlock *acb);
168ad6d6297SScott Long static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb);
16935689395SXin LI static u_int32_t arcmsr_Read_iop_rqbuffer_data(struct AdapterControlBlock *acb, struct QBUFFER *prbuffer);
1707a7bc959SXin LI static void arcmsr_Write_data_2iop_wqbuffer(struct AdapterControlBlock *acb);
171ad6d6297SScott Long static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb);
172ad6d6297SScott Long static void arcmsr_srb_complete(struct CommandControlBlock *srb, int stand_flag);
173ad6d6297SScott Long static void arcmsr_iop_reset(struct AdapterControlBlock *acb);
174ad6d6297SScott Long static void arcmsr_report_sense_info(struct CommandControlBlock *srb);
175ad6d6297SScott Long static void arcmsr_build_srb(struct CommandControlBlock *srb, bus_dma_segment_t *dm_segs, u_int32_t nseg);
176ad6d6297SScott Long static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb *pccb);
177ad6d6297SScott Long static int arcmsr_resume(device_t dev);
178ad6d6297SScott Long static int arcmsr_suspend(device_t dev);
179d74001adSXin LI static void arcmsr_rescanLun_cb(struct cam_periph *periph, union ccb *ccb);
180d74001adSXin LI static void arcmsr_polling_devmap(void *arg);
18122f2616bSXin LI static void arcmsr_srb_timeout(void *arg);
1827a7bc959SXin LI static void arcmsr_hbd_postqueue_isr(struct AdapterControlBlock *acb);
183a1103e04SXin LI static void arcmsr_hbe_postqueue_isr(struct AdapterControlBlock *acb);
184fa42a0bfSXin LI static void arcmsr_hbf_postqueue_isr(struct AdapterControlBlock *acb);
185fc5ef1caSXin LI static void arcmsr_teardown_intr(device_t dev, struct AdapterControlBlock *acb);
18622f2616bSXin LI #ifdef ARCMSR_DEBUG1
18722f2616bSXin LI static void arcmsr_dump_data(struct AdapterControlBlock *acb);
18822f2616bSXin LI #endif
189f1c579b1SScott Long /*
190f1c579b1SScott Long **************************************************************************
191ad6d6297SScott Long **************************************************************************
192ad6d6297SScott Long */
193ad6d6297SScott Long static void UDELAY(u_int32_t us) { DELAY(us); }
194ad6d6297SScott Long /*
195ad6d6297SScott Long **************************************************************************
196f1c579b1SScott Long **************************************************************************
197f1c579b1SScott Long */
198231c8b71SXin LI static bus_dmamap_callback_t arcmsr_map_free_srb;
199231c8b71SXin LI static bus_dmamap_callback_t arcmsr_execute_srb;
200f1c579b1SScott Long /*
201f1c579b1SScott Long **************************************************************************
202f1c579b1SScott Long **************************************************************************
203f1c579b1SScott Long */
204f1c579b1SScott Long static d_open_t	arcmsr_open;
205f1c579b1SScott Long static d_close_t arcmsr_close;
206f1c579b1SScott Long static d_ioctl_t arcmsr_ioctl;
207f1c579b1SScott Long 
208f1c579b1SScott Long static device_method_t arcmsr_methods[]={
209f1c579b1SScott Long 	DEVMETHOD(device_probe,		arcmsr_probe),
210f1c579b1SScott Long 	DEVMETHOD(device_attach,	arcmsr_attach),
211f1c579b1SScott Long 	DEVMETHOD(device_detach,	arcmsr_detach),
212f1c579b1SScott Long 	DEVMETHOD(device_shutdown,	arcmsr_shutdown),
213ad6d6297SScott Long 	DEVMETHOD(device_suspend,	arcmsr_suspend),
214ad6d6297SScott Long 	DEVMETHOD(device_resume,	arcmsr_resume),
2154b7ec270SMarius Strobl 	DEVMETHOD_END
216f1c579b1SScott Long };
217f1c579b1SScott Long 
218f1c579b1SScott Long static driver_t arcmsr_driver={
219ad6d6297SScott Long 	"arcmsr", arcmsr_methods, sizeof(struct AdapterControlBlock)
220f1c579b1SScott Long };
221f1c579b1SScott Long 
2220d6d8bacSJohn Baldwin DRIVER_MODULE(arcmsr, pci, arcmsr_driver, 0, 0);
223d3cf342dSScott Long MODULE_DEPEND(arcmsr, pci, 1, 1, 1);
224d3cf342dSScott Long MODULE_DEPEND(arcmsr, cam, 1, 1, 1);
225ad6d6297SScott Long #ifndef BUS_DMA_COHERENT
226ad6d6297SScott Long 	#define	BUS_DMA_COHERENT	0x04	/* hint: map memory in a coherent way */
227ad6d6297SScott Long #endif
228f1c579b1SScott Long static struct cdevsw arcmsr_cdevsw={
229f1c579b1SScott Long 		.d_version = D_VERSION,
230f1c579b1SScott Long 		.d_open    = arcmsr_open, 	/* open     */
231f1c579b1SScott Long 		.d_close   = arcmsr_close, 	/* close    */
232f1c579b1SScott Long 		.d_ioctl   = arcmsr_ioctl, 	/* ioctl    */
233f1c579b1SScott Long 		.d_name    = "arcmsr", 		/* name     */
234f1c579b1SScott Long 	};
235d74001adSXin LI /*
236d74001adSXin LI **************************************************************************
237d74001adSXin LI **************************************************************************
238d74001adSXin LI */
23900b4e54aSWarner Losh static int arcmsr_open(struct cdev *dev, int flags, int fmt, struct thread *proc)
240f1c579b1SScott Long {
241dac36688SXin LI 	return (0);
242f1c579b1SScott Long }
243f1c579b1SScott Long /*
244f1c579b1SScott Long **************************************************************************
245f1c579b1SScott Long **************************************************************************
246f1c579b1SScott Long */
24700b4e54aSWarner Losh static int arcmsr_close(struct cdev *dev, int flags, int fmt, struct thread *proc)
248f1c579b1SScott Long {
249f1c579b1SScott Long 	return 0;
250f1c579b1SScott Long }
251f1c579b1SScott Long /*
252f1c579b1SScott Long **************************************************************************
253f1c579b1SScott Long **************************************************************************
254f1c579b1SScott Long */
25500b4e54aSWarner Losh static int arcmsr_ioctl(struct cdev *dev, u_long ioctl_cmd, caddr_t arg, int flags, struct thread *proc)
256f1c579b1SScott Long {
257a9e5e04eSJohn Baldwin 	struct AdapterControlBlock *acb = dev->si_drv1;
258f1c579b1SScott Long 
259ad6d6297SScott Long 	return (arcmsr_iop_ioctlcmd(acb, ioctl_cmd, arg));
260f1c579b1SScott Long }
261f1c579b1SScott Long /*
26244f05562SScott Long **********************************************************************
26344f05562SScott Long **********************************************************************
26444f05562SScott Long */
26544f05562SScott Long static u_int32_t arcmsr_disable_allintr( struct AdapterControlBlock *acb)
26644f05562SScott Long {
26744f05562SScott Long 	u_int32_t intmask_org = 0;
26844f05562SScott Long 
26944f05562SScott Long 	switch (acb->adapter_type) {
27044f05562SScott Long 	case ACB_ADAPTER_TYPE_A: {
27144f05562SScott Long 			/* disable all outbound interrupt */
272d74001adSXin LI 			intmask_org = CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intmask); /* disable outbound message0 int */
273d74001adSXin LI 			CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intmask, intmask_org|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE);
27444f05562SScott Long 		}
27544f05562SScott Long 		break;
27644f05562SScott Long 	case ACB_ADAPTER_TYPE_B: {
277b23a1998SXin LI 			struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
27844f05562SScott Long 			/* disable all outbound interrupt */
279b23a1998SXin LI 			intmask_org = READ_CHIP_REG32(0, phbbmu->iop2drv_doorbell_mask)
280b23a1998SXin LI 						& (~ARCMSR_IOP2DRV_MESSAGE_CMD_DONE); /* disable outbound message0 int */
281b23a1998SXin LI 			WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell_mask, 0); /* disable all interrupt */
282d74001adSXin LI 		}
283d74001adSXin LI 		break;
284d74001adSXin LI 	case ACB_ADAPTER_TYPE_C: {
285d74001adSXin LI 			/* disable all outbound interrupt */
286d74001adSXin LI 			intmask_org = CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_mask); /* disable outbound message0 int */
287d74001adSXin LI 			CHIP_REG_WRITE32(HBC_MessageUnit, 0, host_int_mask, intmask_org|ARCMSR_HBCMU_ALL_INTMASKENABLE);
28844f05562SScott Long 		}
28944f05562SScott Long 		break;
2907a7bc959SXin LI 	case ACB_ADAPTER_TYPE_D: {
2917a7bc959SXin LI 			/* disable all outbound interrupt */
2927a7bc959SXin LI 			intmask_org = CHIP_REG_READ32(HBD_MessageUnit, 0, pcief0_int_enable); /* disable outbound message0 int */
2937a7bc959SXin LI 			CHIP_REG_WRITE32(HBD_MessageUnit, 0, pcief0_int_enable, ARCMSR_HBDMU_ALL_INT_DISABLE);
2947a7bc959SXin LI 		}
2957a7bc959SXin LI 		break;
296fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_E:
297fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_F: {
298a1103e04SXin LI 			/* disable all outbound interrupt */
299fa42a0bfSXin LI 			intmask_org = CHIP_REG_READ32(HBE_MessageUnit, 0, host_int_mask); /* disable outbound message0 int */
300a1103e04SXin LI 			CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_mask, intmask_org | ARCMSR_HBEMU_ALL_INTMASKENABLE);
301a1103e04SXin LI 		}
302a1103e04SXin LI 		break;
30344f05562SScott Long 	}
30444f05562SScott Long 	return (intmask_org);
30544f05562SScott Long }
30644f05562SScott Long /*
30744f05562SScott Long **********************************************************************
30844f05562SScott Long **********************************************************************
30944f05562SScott Long */
31044f05562SScott Long static void arcmsr_enable_allintr( struct AdapterControlBlock *acb, u_int32_t intmask_org)
31144f05562SScott Long {
31244f05562SScott Long 	u_int32_t mask;
31344f05562SScott Long 
31444f05562SScott Long 	switch (acb->adapter_type) {
31544f05562SScott Long 	case ACB_ADAPTER_TYPE_A: {
31644f05562SScott Long 			/* enable outbound Post Queue, outbound doorbell Interrupt */
317d74001adSXin LI 			mask = ~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE|ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE|ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE);
31844f05562SScott Long 			CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intmask, intmask_org & mask);
31944f05562SScott Long 			acb->outbound_int_enable = ~(intmask_org & mask) & 0x000000ff;
32044f05562SScott Long 		}
32144f05562SScott Long 		break;
32244f05562SScott Long 	case ACB_ADAPTER_TYPE_B: {
323b23a1998SXin LI 			struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
324d74001adSXin LI 			/* enable ARCMSR_IOP2DRV_MESSAGE_CMD_DONE */
325d74001adSXin LI 			mask = (ARCMSR_IOP2DRV_DATA_WRITE_OK|ARCMSR_IOP2DRV_DATA_READ_OK|ARCMSR_IOP2DRV_CDB_DONE|ARCMSR_IOP2DRV_MESSAGE_CMD_DONE);
326b23a1998SXin LI 			WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell_mask, intmask_org | mask); /*1=interrupt enable, 0=interrupt disable*/
32744f05562SScott Long 			acb->outbound_int_enable = (intmask_org | mask) & 0x0000000f;
32844f05562SScott Long 		}
32944f05562SScott Long 		break;
330d74001adSXin LI 	case ACB_ADAPTER_TYPE_C: {
331d74001adSXin LI 			/* enable outbound Post Queue, outbound doorbell Interrupt */
332d74001adSXin LI 			mask = ~(ARCMSR_HBCMU_UTILITY_A_ISR_MASK | ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR_MASK | ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR_MASK);
333d74001adSXin LI 			CHIP_REG_WRITE32(HBC_MessageUnit, 0, host_int_mask, intmask_org & mask);
334d74001adSXin LI 			acb->outbound_int_enable = ~(intmask_org & mask) & 0x0000000f;
335d74001adSXin LI 		}
336d74001adSXin LI 		break;
3377a7bc959SXin LI 	case ACB_ADAPTER_TYPE_D: {
3387a7bc959SXin LI 			/* enable outbound Post Queue, outbound doorbell Interrupt */
3397a7bc959SXin LI 			mask = ARCMSR_HBDMU_ALL_INT_ENABLE;
3407a7bc959SXin LI 			CHIP_REG_WRITE32(HBD_MessageUnit, 0, pcief0_int_enable, intmask_org | mask);
3417a7bc959SXin LI 			CHIP_REG_READ32(HBD_MessageUnit, 0, pcief0_int_enable);
3427a7bc959SXin LI 			acb->outbound_int_enable = mask;
3437a7bc959SXin LI 		}
3447a7bc959SXin LI 		break;
345fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_E:
346fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_F: {
347a1103e04SXin LI 			/* enable outbound Post Queue, outbound doorbell Interrupt */
348a1103e04SXin LI 			mask = ~(ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR | ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR);
349a1103e04SXin LI 			CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_mask, intmask_org & mask);
350a1103e04SXin LI 			acb->outbound_int_enable = ~(intmask_org & mask) & 0x0000000f;
351a1103e04SXin LI 		}
352a1103e04SXin LI 		break;
35344f05562SScott Long 	}
35444f05562SScott Long }
35544f05562SScott Long /*
35644f05562SScott Long **********************************************************************
35744f05562SScott Long **********************************************************************
35844f05562SScott Long */
35944f05562SScott Long static u_int8_t arcmsr_hba_wait_msgint_ready(struct AdapterControlBlock *acb)
36044f05562SScott Long {
36144f05562SScott Long 	u_int32_t Index;
36244f05562SScott Long 	u_int8_t Retries = 0x00;
36344f05562SScott Long 
36444f05562SScott Long 	do {
36544f05562SScott Long 		for(Index=0; Index < 100; Index++) {
366d74001adSXin LI 			if(CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) {
367d74001adSXin LI 				CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, ARCMSR_MU_OUTBOUND_MESSAGE0_INT);/*clear interrupt*/
36844f05562SScott Long 				return TRUE;
36944f05562SScott Long 			}
37044f05562SScott Long 			UDELAY(10000);
37144f05562SScott Long 		}/*max 1 seconds*/
37244f05562SScott Long 	}while(Retries++ < 20);/*max 20 sec*/
373dac36688SXin LI 	return (FALSE);
37444f05562SScott Long }
37544f05562SScott Long /*
37644f05562SScott Long **********************************************************************
37744f05562SScott Long **********************************************************************
37844f05562SScott Long */
37944f05562SScott Long static u_int8_t arcmsr_hbb_wait_msgint_ready(struct AdapterControlBlock *acb)
38044f05562SScott Long {
38144f05562SScott Long 	u_int32_t Index;
38244f05562SScott Long 	u_int8_t Retries = 0x00;
383b23a1998SXin LI 	struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
38444f05562SScott Long 
38544f05562SScott Long 	do {
38644f05562SScott Long 		for(Index=0; Index < 100; Index++) {
387b23a1998SXin LI 			if(READ_CHIP_REG32(0, phbbmu->iop2drv_doorbell) & ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) {
388b23a1998SXin LI 				WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell, ARCMSR_MESSAGE_INT_CLEAR_PATTERN);/*clear interrupt*/
389b23a1998SXin LI 				WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT);
390d74001adSXin LI 				return TRUE;
391d74001adSXin LI 			}
392d74001adSXin LI 			UDELAY(10000);
393d74001adSXin LI 		}/*max 1 seconds*/
394d74001adSXin LI 	}while(Retries++ < 20);/*max 20 sec*/
395dac36688SXin LI 	return (FALSE);
396d74001adSXin LI }
397d74001adSXin LI /*
398d74001adSXin LI **********************************************************************
399d74001adSXin LI **********************************************************************
400d74001adSXin LI */
401d74001adSXin LI static u_int8_t arcmsr_hbc_wait_msgint_ready(struct AdapterControlBlock *acb)
402d74001adSXin LI {
403d74001adSXin LI 	u_int32_t Index;
404d74001adSXin LI 	u_int8_t Retries = 0x00;
405d74001adSXin LI 
406d74001adSXin LI 	do {
407d74001adSXin LI 		for(Index=0; Index < 100; Index++) {
408d74001adSXin LI 			if(CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) {
409d74001adSXin LI 				CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR);/*clear interrupt*/
41044f05562SScott Long 				return TRUE;
41144f05562SScott Long 			}
41244f05562SScott Long 			UDELAY(10000);
41344f05562SScott Long 		}/*max 1 seconds*/
41444f05562SScott Long 	}while(Retries++ < 20);/*max 20 sec*/
415dac36688SXin LI 	return (FALSE);
41644f05562SScott Long }
41744f05562SScott Long /*
4187a7bc959SXin LI **********************************************************************
4197a7bc959SXin LI **********************************************************************
4207a7bc959SXin LI */
4217a7bc959SXin LI static u_int8_t arcmsr_hbd_wait_msgint_ready(struct AdapterControlBlock *acb)
4227a7bc959SXin LI {
4237a7bc959SXin LI 	u_int32_t Index;
4247a7bc959SXin LI 	u_int8_t Retries = 0x00;
4257a7bc959SXin LI 
4267a7bc959SXin LI 	do {
4277a7bc959SXin LI 		for(Index=0; Index < 100; Index++) {
4287a7bc959SXin LI 			if(CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE) {
4297a7bc959SXin LI 				CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE_CLEAR);/*clear interrupt*/
4307a7bc959SXin LI 				return TRUE;
4317a7bc959SXin LI 			}
4327a7bc959SXin LI 			UDELAY(10000);
4337a7bc959SXin LI 		}/*max 1 seconds*/
4347a7bc959SXin LI 	}while(Retries++ < 20);/*max 20 sec*/
4357a7bc959SXin LI 	return (FALSE);
4367a7bc959SXin LI }
4377a7bc959SXin LI /*
438a1103e04SXin LI **********************************************************************
439a1103e04SXin LI **********************************************************************
440a1103e04SXin LI */
441a1103e04SXin LI static u_int8_t arcmsr_hbe_wait_msgint_ready(struct AdapterControlBlock *acb)
442a1103e04SXin LI {
443a1103e04SXin LI 	u_int32_t Index, read_doorbell;
444a1103e04SXin LI 	u_int8_t Retries = 0x00;
445a1103e04SXin LI 
446a1103e04SXin LI 	do {
447a1103e04SXin LI 		for(Index=0; Index < 100; Index++) {
448a1103e04SXin LI 			read_doorbell = CHIP_REG_READ32(HBE_MessageUnit, 0, iobound_doorbell);
449a1103e04SXin LI 			if((read_doorbell ^ acb->in_doorbell) & ARCMSR_HBEMU_IOP2DRV_MESSAGE_CMD_DONE) {
450a1103e04SXin LI 				CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_status, 0);/*clear interrupt*/
451a1103e04SXin LI 				acb->in_doorbell = read_doorbell;
452a1103e04SXin LI 				return TRUE;
453a1103e04SXin LI 			}
454a1103e04SXin LI 			UDELAY(10000);
455a1103e04SXin LI 		}/*max 1 seconds*/
456a1103e04SXin LI 	}while(Retries++ < 20);/*max 20 sec*/
457a1103e04SXin LI 	return (FALSE);
458a1103e04SXin LI }
459a1103e04SXin LI /*
46044f05562SScott Long ************************************************************************
46144f05562SScott Long ************************************************************************
46244f05562SScott Long */
46344f05562SScott Long static void arcmsr_flush_hba_cache(struct AdapterControlBlock *acb)
46444f05562SScott Long {
46544f05562SScott Long 	int retry_count = 30;/* enlarge wait flush adapter cache time: 10 minute */
46644f05562SScott Long 
467d74001adSXin LI 	CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE);
46844f05562SScott Long 	do {
46944f05562SScott Long 		if(arcmsr_hba_wait_msgint_ready(acb)) {
47044f05562SScott Long 			break;
47144f05562SScott Long 		} else {
47244f05562SScott Long 			retry_count--;
47344f05562SScott Long 		}
47444f05562SScott Long 	}while(retry_count != 0);
47544f05562SScott Long }
47644f05562SScott Long /*
47744f05562SScott Long ************************************************************************
47844f05562SScott Long ************************************************************************
47944f05562SScott Long */
48044f05562SScott Long static void arcmsr_flush_hbb_cache(struct AdapterControlBlock *acb)
48144f05562SScott Long {
48244f05562SScott Long 	int retry_count = 30;/* enlarge wait flush adapter cache time: 10 minute */
483b23a1998SXin LI 	struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
48444f05562SScott Long 
485b23a1998SXin LI 	WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_FLUSH_CACHE);
48644f05562SScott Long 	do {
48744f05562SScott Long 		if(arcmsr_hbb_wait_msgint_ready(acb)) {
48844f05562SScott Long 			break;
48944f05562SScott Long 		} else {
49044f05562SScott Long 			retry_count--;
49144f05562SScott Long 		}
49244f05562SScott Long 	}while(retry_count != 0);
49344f05562SScott Long }
49444f05562SScott Long /*
49544f05562SScott Long ************************************************************************
49644f05562SScott Long ************************************************************************
49744f05562SScott Long */
498d74001adSXin LI static void arcmsr_flush_hbc_cache(struct AdapterControlBlock *acb)
499d74001adSXin LI {
500d74001adSXin LI 	int retry_count = 30;/* enlarge wait flush adapter cache time: 10 minute */
501d74001adSXin LI 
502d74001adSXin LI 	CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE);
503d74001adSXin LI 	CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE);
504d74001adSXin LI 	do {
505d74001adSXin LI 		if(arcmsr_hbc_wait_msgint_ready(acb)) {
506d74001adSXin LI 			break;
507d74001adSXin LI 		} else {
508d74001adSXin LI 			retry_count--;
509d74001adSXin LI 		}
510d74001adSXin LI 	}while(retry_count != 0);
511d74001adSXin LI }
512d74001adSXin LI /*
513d74001adSXin LI ************************************************************************
514d74001adSXin LI ************************************************************************
515d74001adSXin LI */
5167a7bc959SXin LI static void arcmsr_flush_hbd_cache(struct AdapterControlBlock *acb)
5177a7bc959SXin LI {
5187a7bc959SXin LI 	int retry_count = 30; /* enlarge wait flush adapter cache time: 10 minute */
5197a7bc959SXin LI 
5207a7bc959SXin LI 	CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE);
5217a7bc959SXin LI 	do {
5227a7bc959SXin LI 		if(arcmsr_hbd_wait_msgint_ready(acb)) {
5237a7bc959SXin LI 			break;
5247a7bc959SXin LI 		} else {
5257a7bc959SXin LI 			retry_count--;
5267a7bc959SXin LI 		}
5277a7bc959SXin LI 	}while(retry_count != 0);
5287a7bc959SXin LI }
5297a7bc959SXin LI /*
5307a7bc959SXin LI ************************************************************************
5317a7bc959SXin LI ************************************************************************
5327a7bc959SXin LI */
533a1103e04SXin LI static void arcmsr_flush_hbe_cache(struct AdapterControlBlock *acb)
534a1103e04SXin LI {
535a1103e04SXin LI 	int retry_count = 30;/* enlarge wait flush adapter cache time: 10 minute */
536a1103e04SXin LI 
537a1103e04SXin LI 	CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE);
538a1103e04SXin LI 	acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
539a1103e04SXin LI 	CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
540a1103e04SXin LI 	do {
541a1103e04SXin LI 		if(arcmsr_hbe_wait_msgint_ready(acb)) {
542a1103e04SXin LI 			break;
543a1103e04SXin LI 		} else {
544a1103e04SXin LI 			retry_count--;
545a1103e04SXin LI 		}
546a1103e04SXin LI 	}while(retry_count != 0);
547a1103e04SXin LI }
548a1103e04SXin LI /*
549a1103e04SXin LI ************************************************************************
550a1103e04SXin LI ************************************************************************
551a1103e04SXin LI */
55244f05562SScott Long static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb)
55344f05562SScott Long {
55444f05562SScott Long 	switch (acb->adapter_type) {
55544f05562SScott Long 	case ACB_ADAPTER_TYPE_A: {
55644f05562SScott Long 			arcmsr_flush_hba_cache(acb);
55744f05562SScott Long 		}
55844f05562SScott Long 		break;
55944f05562SScott Long 	case ACB_ADAPTER_TYPE_B: {
56044f05562SScott Long 			arcmsr_flush_hbb_cache(acb);
56144f05562SScott Long 		}
56244f05562SScott Long 		break;
563d74001adSXin LI 	case ACB_ADAPTER_TYPE_C: {
564d74001adSXin LI 			arcmsr_flush_hbc_cache(acb);
565d74001adSXin LI 		}
566d74001adSXin LI 		break;
5677a7bc959SXin LI 	case ACB_ADAPTER_TYPE_D: {
5687a7bc959SXin LI 			arcmsr_flush_hbd_cache(acb);
5697a7bc959SXin LI 		}
5707a7bc959SXin LI 		break;
571fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_E:
572fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_F: {
573a1103e04SXin LI 			arcmsr_flush_hbe_cache(acb);
574a1103e04SXin LI 		}
575a1103e04SXin LI 		break;
57644f05562SScott Long 	}
57744f05562SScott Long }
57844f05562SScott Long /*
579ad6d6297SScott Long *******************************************************************************
580ad6d6297SScott Long *******************************************************************************
581f1c579b1SScott Long */
582ad6d6297SScott Long static int arcmsr_suspend(device_t dev)
583f1c579b1SScott Long {
584ad6d6297SScott Long 	struct AdapterControlBlock	*acb = device_get_softc(dev);
585f1c579b1SScott Long 
586ad6d6297SScott Long 	/* flush controller */
587ad6d6297SScott Long 	arcmsr_iop_parking(acb);
588d74001adSXin LI 	/* disable all outbound interrupt */
589d74001adSXin LI 	arcmsr_disable_allintr(acb);
590ad6d6297SScott Long 	return(0);
591ad6d6297SScott Long }
592ad6d6297SScott Long /*
593ad6d6297SScott Long *******************************************************************************
594ad6d6297SScott Long *******************************************************************************
595ad6d6297SScott Long */
596ad6d6297SScott Long static int arcmsr_resume(device_t dev)
597ad6d6297SScott Long {
598ad6d6297SScott Long 	struct AdapterControlBlock	*acb = device_get_softc(dev);
599f1c579b1SScott Long 
600ad6d6297SScott Long 	arcmsr_iop_init(acb);
601ad6d6297SScott Long 	return(0);
602f1c579b1SScott Long }
603f1c579b1SScott Long /*
604f1c579b1SScott Long *********************************************************************************
605f1c579b1SScott Long *********************************************************************************
606f1c579b1SScott Long */
607ad6d6297SScott Long static void arcmsr_async(void *cb_arg, u_int32_t code, struct cam_path *path, void *arg)
608f1c579b1SScott Long {
609ad6d6297SScott Long 	u_int8_t target_id, target_lun;
610f1c579b1SScott Long 
611ad6d6297SScott Long 	switch (code) {
612f1c579b1SScott Long 	case AC_LOST_DEVICE:
613f1c579b1SScott Long 		target_id = xpt_path_target_id(path);
614f1c579b1SScott Long 		target_lun = xpt_path_lun_id(path);
615d74001adSXin LI 		if((target_id > ARCMSR_MAX_TARGETID) || (target_lun > ARCMSR_MAX_TARGETLUN)) {
616f1c579b1SScott Long 			break;
617f1c579b1SScott Long 		}
618f1c579b1SScott Long 		break;
619f1c579b1SScott Long 	default:
620f1c579b1SScott Long 		break;
621f1c579b1SScott Long 	}
622f1c579b1SScott Long }
623f1c579b1SScott Long /*
624f1c579b1SScott Long **********************************************************************
625f1c579b1SScott Long **********************************************************************
626f1c579b1SScott Long */
627ad6d6297SScott Long static void arcmsr_report_sense_info(struct CommandControlBlock *srb)
628f1c579b1SScott Long {
629ad6d6297SScott Long 	union ccb *pccb = srb->pccb;
630f1c579b1SScott Long 
631ad6d6297SScott Long 	pccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
632ad6d6297SScott Long 	pccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
633dac36688SXin LI 	if(pccb->csio.sense_len) {
634ad6d6297SScott Long 		memset(&pccb->csio.sense_data, 0, sizeof(pccb->csio.sense_data));
635ad6d6297SScott Long 		memcpy(&pccb->csio.sense_data, srb->arcmsr_cdb.SenseData,
636ad6d6297SScott Long 		get_min(sizeof(struct SENSE_DATA), sizeof(pccb->csio.sense_data)));
637ad6d6297SScott Long 		((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70); /* Valid,ErrorCode */
638f1c579b1SScott Long 		pccb->ccb_h.status |= CAM_AUTOSNS_VALID;
639f1c579b1SScott Long 	}
640f1c579b1SScott Long }
641f1c579b1SScott Long /*
642f1c579b1SScott Long *********************************************************************
64344f05562SScott Long *********************************************************************
64444f05562SScott Long */
64544f05562SScott Long static void arcmsr_abort_hba_allcmd(struct AdapterControlBlock *acb)
64644f05562SScott Long {
64744f05562SScott Long 	CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_ABORT_CMD);
64844f05562SScott Long 	if(!arcmsr_hba_wait_msgint_ready(acb)) {
649d74001adSXin LI 		printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit);
65044f05562SScott Long 	}
65144f05562SScott Long }
65244f05562SScott Long /*
65344f05562SScott Long *********************************************************************
65444f05562SScott Long *********************************************************************
65544f05562SScott Long */
65644f05562SScott Long static void arcmsr_abort_hbb_allcmd(struct AdapterControlBlock *acb)
65744f05562SScott Long {
658b23a1998SXin LI 	struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
659b23a1998SXin LI 	WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_ABORT_CMD);
66044f05562SScott Long 	if(!arcmsr_hbb_wait_msgint_ready(acb)) {
661d74001adSXin LI 		printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit);
662d74001adSXin LI 	}
663d74001adSXin LI }
664d74001adSXin LI /*
665d74001adSXin LI *********************************************************************
666d74001adSXin LI *********************************************************************
667d74001adSXin LI */
668d74001adSXin LI static void arcmsr_abort_hbc_allcmd(struct AdapterControlBlock *acb)
669d74001adSXin LI {
670d74001adSXin LI 	CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_ABORT_CMD);
671d74001adSXin LI 	CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE);
672d74001adSXin LI 	if(!arcmsr_hbc_wait_msgint_ready(acb)) {
673d74001adSXin LI 		printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit);
67444f05562SScott Long 	}
67544f05562SScott Long }
67644f05562SScott Long /*
67744f05562SScott Long *********************************************************************
678f1c579b1SScott Long *********************************************************************
679f1c579b1SScott Long */
6807a7bc959SXin LI static void arcmsr_abort_hbd_allcmd(struct AdapterControlBlock *acb)
6817a7bc959SXin LI {
6827a7bc959SXin LI 	CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_ABORT_CMD);
6837a7bc959SXin LI 	if(!arcmsr_hbd_wait_msgint_ready(acb)) {
6847a7bc959SXin LI 		printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit);
6857a7bc959SXin LI 	}
6867a7bc959SXin LI }
6877a7bc959SXin LI /*
6887a7bc959SXin LI *********************************************************************
6897a7bc959SXin LI *********************************************************************
6907a7bc959SXin LI */
691a1103e04SXin LI static void arcmsr_abort_hbe_allcmd(struct AdapterControlBlock *acb)
692a1103e04SXin LI {
693a1103e04SXin LI 	CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_ABORT_CMD);
694a1103e04SXin LI 	acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
695a1103e04SXin LI 	CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
696a1103e04SXin LI 	if(!arcmsr_hbe_wait_msgint_ready(acb)) {
697a1103e04SXin LI 		printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit);
698a1103e04SXin LI 	}
699a1103e04SXin LI }
700a1103e04SXin LI /*
701a1103e04SXin LI *********************************************************************
702a1103e04SXin LI *********************************************************************
703a1103e04SXin LI */
704ad6d6297SScott Long static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb)
705f1c579b1SScott Long {
70644f05562SScott Long 	switch (acb->adapter_type) {
70744f05562SScott Long 	case ACB_ADAPTER_TYPE_A: {
70844f05562SScott Long 			arcmsr_abort_hba_allcmd(acb);
70944f05562SScott Long 		}
71044f05562SScott Long 		break;
71144f05562SScott Long 	case ACB_ADAPTER_TYPE_B: {
71244f05562SScott Long 			arcmsr_abort_hbb_allcmd(acb);
71344f05562SScott Long 		}
71444f05562SScott Long 		break;
715d74001adSXin LI 	case ACB_ADAPTER_TYPE_C: {
716d74001adSXin LI 			arcmsr_abort_hbc_allcmd(acb);
717d74001adSXin LI 		}
718d74001adSXin LI 		break;
7197a7bc959SXin LI 	case ACB_ADAPTER_TYPE_D: {
7207a7bc959SXin LI 			arcmsr_abort_hbd_allcmd(acb);
7217a7bc959SXin LI 		}
7227a7bc959SXin LI 		break;
723fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_E:
724fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_F: {
725a1103e04SXin LI 			arcmsr_abort_hbe_allcmd(acb);
726a1103e04SXin LI 		}
727a1103e04SXin LI 		break;
72844f05562SScott Long 	}
72944f05562SScott Long }
73044f05562SScott Long /*
731231c8b71SXin LI **********************************************************************
732231c8b71SXin LI **********************************************************************
733231c8b71SXin LI */
734231c8b71SXin LI static void arcmsr_srb_complete(struct CommandControlBlock *srb, int stand_flag)
735231c8b71SXin LI {
736231c8b71SXin LI 	struct AdapterControlBlock *acb = srb->acb;
737231c8b71SXin LI 	union ccb *pccb = srb->pccb;
738231c8b71SXin LI 
73922f2616bSXin LI 	if(srb->srb_flags & SRB_FLAG_TIMER_START)
74022f2616bSXin LI 		callout_stop(&srb->ccb_callout);
741231c8b71SXin LI 	if((pccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
742231c8b71SXin LI 		bus_dmasync_op_t op;
743231c8b71SXin LI 
744231c8b71SXin LI 		if((pccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
745231c8b71SXin LI 			op = BUS_DMASYNC_POSTREAD;
746231c8b71SXin LI 		} else {
747231c8b71SXin LI 			op = BUS_DMASYNC_POSTWRITE;
748231c8b71SXin LI 		}
749231c8b71SXin LI 		bus_dmamap_sync(acb->dm_segs_dmat, srb->dm_segs_dmamap, op);
750231c8b71SXin LI 		bus_dmamap_unload(acb->dm_segs_dmat, srb->dm_segs_dmamap);
751231c8b71SXin LI 	}
752231c8b71SXin LI 	if(stand_flag == 1) {
753231c8b71SXin LI 		atomic_subtract_int(&acb->srboutstandingcount, 1);
754231c8b71SXin LI 		if((acb->acb_flags & ACB_F_CAM_DEV_QFRZN) && (
755abfdbca9SXin LI 		acb->srboutstandingcount < (acb->maxOutstanding -10))) {
756231c8b71SXin LI 			acb->acb_flags &= ~ACB_F_CAM_DEV_QFRZN;
757231c8b71SXin LI 			pccb->ccb_h.status |= CAM_RELEASE_SIMQ;
758231c8b71SXin LI 		}
759231c8b71SXin LI 	}
76022f2616bSXin LI 	if(srb->srb_state != ARCMSR_SRB_TIMEOUT)
76122f2616bSXin LI 		arcmsr_free_srb(srb);
76222f2616bSXin LI 	acb->pktReturnCount++;
763231c8b71SXin LI 	xpt_done(pccb);
764231c8b71SXin LI }
765231c8b71SXin LI /*
76644f05562SScott Long **************************************************************************
76744f05562SScott Long **************************************************************************
76844f05562SScott Long */
769d74001adSXin LI static void arcmsr_report_srb_state(struct AdapterControlBlock *acb, struct CommandControlBlock *srb, u_int16_t error)
77044f05562SScott Long {
77144f05562SScott Long 	int target, lun;
77244f05562SScott Long 
77344f05562SScott Long 	target = srb->pccb->ccb_h.target_id;
77444f05562SScott Long 	lun = srb->pccb->ccb_h.target_lun;
775d74001adSXin LI 	if(error == FALSE) {
77644f05562SScott Long 		if(acb->devstate[target][lun] == ARECA_RAID_GONE) {
77744f05562SScott Long 			acb->devstate[target][lun] = ARECA_RAID_GOOD;
77844f05562SScott Long 		}
77944f05562SScott Long 		srb->pccb->ccb_h.status |= CAM_REQ_CMP;
78044f05562SScott Long 		arcmsr_srb_complete(srb, 1);
78144f05562SScott Long 	} else {
78244f05562SScott Long 		switch(srb->arcmsr_cdb.DeviceStatus) {
78344f05562SScott Long 		case ARCMSR_DEV_SELECT_TIMEOUT: {
78444f05562SScott Long 				if(acb->devstate[target][lun] == ARECA_RAID_GOOD) {
785d74001adSXin LI 					printf( "arcmsr%d: Target=%x, Lun=%x, selection timeout, raid volume was lost\n", acb->pci_unit, target, lun);
786ad6d6297SScott Long 				}
78744f05562SScott Long 				acb->devstate[target][lun] = ARECA_RAID_GONE;
788d74001adSXin LI 				srb->pccb->ccb_h.status |= CAM_DEV_NOT_THERE;
78944f05562SScott Long 				arcmsr_srb_complete(srb, 1);
79044f05562SScott Long 			}
79144f05562SScott Long 			break;
79244f05562SScott Long 		case ARCMSR_DEV_ABORTED:
79344f05562SScott Long 		case ARCMSR_DEV_INIT_FAIL: {
79444f05562SScott Long 				acb->devstate[target][lun] = ARECA_RAID_GONE;
79544f05562SScott Long 				srb->pccb->ccb_h.status |= CAM_DEV_NOT_THERE;
79644f05562SScott Long 				arcmsr_srb_complete(srb, 1);
79744f05562SScott Long 			}
79844f05562SScott Long 			break;
79944f05562SScott Long 		case SCSISTAT_CHECK_CONDITION: {
80044f05562SScott Long 				acb->devstate[target][lun] = ARECA_RAID_GOOD;
80144f05562SScott Long 				arcmsr_report_sense_info(srb);
80244f05562SScott Long 				arcmsr_srb_complete(srb, 1);
80344f05562SScott Long 			}
80444f05562SScott Long 			break;
80544f05562SScott Long 		default:
80610d66948SKevin Lo 			printf("arcmsr%d: scsi id=%d lun=%d isr got command error done,but got unknown DeviceStatus=0x%x \n"
807d74001adSXin LI 					, acb->pci_unit, target, lun ,srb->arcmsr_cdb.DeviceStatus);
80844f05562SScott Long 			acb->devstate[target][lun] = ARECA_RAID_GONE;
80944f05562SScott Long 			srb->pccb->ccb_h.status |= CAM_UNCOR_PARITY;
81010d66948SKevin Lo 			/*unknown error or crc error just for retry*/
81144f05562SScott Long 			arcmsr_srb_complete(srb, 1);
81244f05562SScott Long 			break;
81344f05562SScott Long 		}
81444f05562SScott Long 	}
81544f05562SScott Long }
81644f05562SScott Long /*
81744f05562SScott Long **************************************************************************
81844f05562SScott Long **************************************************************************
81944f05562SScott Long */
820d74001adSXin LI static void arcmsr_drain_donequeue(struct AdapterControlBlock *acb, u_int32_t flag_srb, u_int16_t error)
82144f05562SScott Long {
82244f05562SScott Long 	struct CommandControlBlock *srb;
82344f05562SScott Long 
82444f05562SScott Long 	/* check if command done with no error*/
825d74001adSXin LI 	switch (acb->adapter_type) {
826fc5ef1caSXin LI 	case ACB_ADAPTER_TYPE_A:
827fc5ef1caSXin LI 	case ACB_ADAPTER_TYPE_B:
828fc5ef1caSXin LI 		srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/
829fc5ef1caSXin LI 		break;
830d74001adSXin LI 	case ACB_ADAPTER_TYPE_C:
8317a7bc959SXin LI 	case ACB_ADAPTER_TYPE_D:
83222f2616bSXin LI 		srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb & 0xFFFFFFE0)); /*frame must be 32 bytes aligned*/
833d74001adSXin LI 		break;
834a1103e04SXin LI 	case ACB_ADAPTER_TYPE_E:
835fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_F:
836a1103e04SXin LI 		srb = acb->psrb_pool[flag_srb];
837a1103e04SXin LI 		break;
838d74001adSXin LI 	default:
839d74001adSXin LI 		srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/
840d74001adSXin LI 		break;
841d74001adSXin LI 	}
84222f2616bSXin LI 	if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) {
84322f2616bSXin LI 		if(srb->srb_state == ARCMSR_SRB_TIMEOUT) {
84422f2616bSXin LI 			arcmsr_free_srb(srb);
84522f2616bSXin LI 			printf("arcmsr%d: srb='%p' return srb has been timeouted\n", acb->pci_unit, srb);
84644f05562SScott Long 			return;
84744f05562SScott Long 		}
84822f2616bSXin LI 		printf("arcmsr%d: return srb has been completed\n"
84922f2616bSXin LI 			"srb='%p' srb_state=0x%x outstanding srb count=%d \n",
85022f2616bSXin LI 			acb->pci_unit, srb, srb->srb_state, acb->srboutstandingcount);
85144f05562SScott Long 		return;
85244f05562SScott Long 	}
853d74001adSXin LI 	arcmsr_report_srb_state(acb, srb, error);
85444f05562SScott Long }
85544f05562SScott Long /*
85622f2616bSXin LI **************************************************************************
85722f2616bSXin LI **************************************************************************
85822f2616bSXin LI */
85922f2616bSXin LI static void	arcmsr_srb_timeout(void *arg)
86022f2616bSXin LI {
86122f2616bSXin LI 	struct CommandControlBlock *srb = (struct CommandControlBlock *)arg;
86222f2616bSXin LI 	struct AdapterControlBlock *acb;
86322f2616bSXin LI 	int target, lun;
86422f2616bSXin LI 	u_int8_t cmd;
86522f2616bSXin LI 
86622f2616bSXin LI 	target = srb->pccb->ccb_h.target_id;
86722f2616bSXin LI 	lun = srb->pccb->ccb_h.target_lun;
86822f2616bSXin LI 	acb = srb->acb;
8697a7bc959SXin LI 	ARCMSR_LOCK_ACQUIRE(&acb->isr_lock);
87022f2616bSXin LI 	if(srb->srb_state == ARCMSR_SRB_START)
87122f2616bSXin LI 	{
8724aa947cbSWarner Losh 		cmd = scsiio_cdb_ptr(&srb->pccb->csio)[0];
87322f2616bSXin LI 		srb->srb_state = ARCMSR_SRB_TIMEOUT;
87422f2616bSXin LI 		srb->pccb->ccb_h.status |= CAM_CMD_TIMEOUT;
87522f2616bSXin LI 		arcmsr_srb_complete(srb, 1);
87622f2616bSXin LI 		printf("arcmsr%d: scsi id %d lun %d cmd=0x%x srb='%p' ccb command time out!\n",
87722f2616bSXin LI 				 acb->pci_unit, target, lun, cmd, srb);
87822f2616bSXin LI 	}
8797a7bc959SXin LI 	ARCMSR_LOCK_RELEASE(&acb->isr_lock);
88022f2616bSXin LI #ifdef ARCMSR_DEBUG1
88122f2616bSXin LI 	arcmsr_dump_data(acb);
88222f2616bSXin LI #endif
88322f2616bSXin LI }
88422f2616bSXin LI 
88522f2616bSXin LI /*
88644f05562SScott Long **********************************************************************
88744f05562SScott Long **********************************************************************
88844f05562SScott Long */
88944f05562SScott Long static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb)
89044f05562SScott Long {
89144f05562SScott Long 	int i=0;
89244f05562SScott Long 	u_int32_t flag_srb;
893d74001adSXin LI 	u_int16_t error;
89444f05562SScott Long 
89544f05562SScott Long 	switch (acb->adapter_type) {
89644f05562SScott Long 	case ACB_ADAPTER_TYPE_A: {
89744f05562SScott Long 			u_int32_t outbound_intstatus;
89844f05562SScott Long 
89944f05562SScott Long 			/*clear and abort all outbound posted Q*/
900d74001adSXin LI 			outbound_intstatus = CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & acb->outbound_int_enable;
901d74001adSXin LI 			CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, outbound_intstatus);/*clear interrupt*/
902d74001adSXin LI 			while(((flag_srb=CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_queueport)) != 0xFFFFFFFF) && (i++ < ARCMSR_MAX_OUTSTANDING_CMD)) {
903d74001adSXin LI 				error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE;
904d74001adSXin LI 				arcmsr_drain_donequeue(acb, flag_srb, error);
90544f05562SScott Long 			}
90644f05562SScott Long 		}
90744f05562SScott Long 		break;
90844f05562SScott Long 	case ACB_ADAPTER_TYPE_B: {
90944f05562SScott Long 			struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu;
91044f05562SScott Long 
91144f05562SScott Long 			/*clear all outbound posted Q*/
912b23a1998SXin LI 			WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell, ARCMSR_DOORBELL_INT_CLEAR_PATTERN); /* clear doorbell interrupt */
91344f05562SScott Long 			for(i=0; i < ARCMSR_MAX_HBB_POSTQUEUE; i++) {
91444f05562SScott Long 				if((flag_srb = phbbmu->done_qbuffer[i]) != 0) {
91544f05562SScott Long 					phbbmu->done_qbuffer[i] = 0;
916d74001adSXin LI 					error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE;
917d74001adSXin LI 					arcmsr_drain_donequeue(acb, flag_srb, error);
91844f05562SScott Long 				}
91944f05562SScott Long 				phbbmu->post_qbuffer[i] = 0;
92044f05562SScott Long 			}/*drain reply FIFO*/
92144f05562SScott Long 			phbbmu->doneq_index = 0;
92244f05562SScott Long 			phbbmu->postq_index = 0;
92344f05562SScott Long 		}
92444f05562SScott Long 		break;
925d74001adSXin LI 	case ACB_ADAPTER_TYPE_C: {
926d74001adSXin LI 			while((CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) && (i++ < ARCMSR_MAX_OUTSTANDING_CMD)) {
927d74001adSXin LI 				flag_srb = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_queueport_low);
928d74001adSXin LI 				error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE;
929d74001adSXin LI 				arcmsr_drain_donequeue(acb, flag_srb, error);
930d74001adSXin LI 			}
931d74001adSXin LI 		}
932d74001adSXin LI 		break;
933fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_D:
9347a7bc959SXin LI 		arcmsr_hbd_postqueue_isr(acb);
9357a7bc959SXin LI 		break;
936fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_E:
937a1103e04SXin LI 		arcmsr_hbe_postqueue_isr(acb);
938fa42a0bfSXin LI 		break;
939fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_F:
940fa42a0bfSXin LI 		arcmsr_hbf_postqueue_isr(acb);
941a1103e04SXin LI 		break;
94244f05562SScott Long 	}
943f1c579b1SScott Long }
944f1c579b1SScott Long /*
945f1c579b1SScott Long ****************************************************************************
946f1c579b1SScott Long ****************************************************************************
947f1c579b1SScott Long */
948ad6d6297SScott Long static void arcmsr_iop_reset(struct AdapterControlBlock *acb)
949f1c579b1SScott Long {
950ad6d6297SScott Long 	struct CommandControlBlock *srb;
95144f05562SScott Long 	u_int32_t intmask_org;
952ad6d6297SScott Long 	u_int32_t i=0;
953f1c579b1SScott Long 
95444f05562SScott Long 	if(acb->srboutstandingcount>0) {
95544f05562SScott Long 		/* disable all outbound interrupt */
95644f05562SScott Long 		intmask_org = arcmsr_disable_allintr(acb);
95744f05562SScott Long 		/*clear and abort all outbound posted Q*/
95844f05562SScott Long 		arcmsr_done4abort_postqueue(acb);
959f1c579b1SScott Long 		/* talk to iop 331 outstanding command aborted*/
960ad6d6297SScott Long 		arcmsr_abort_allcmd(acb);
961ad6d6297SScott Long 		for(i=0; i < ARCMSR_MAX_FREESRB_NUM; i++) {
962ad6d6297SScott Long 			srb = acb->psrb_pool[i];
96322f2616bSXin LI 			if(srb->srb_state == ARCMSR_SRB_START) {
96422f2616bSXin LI 				srb->srb_state = ARCMSR_SRB_ABORTED;
965ad6d6297SScott Long 				srb->pccb->ccb_h.status |= CAM_REQ_ABORTED;
966ad6d6297SScott Long 				arcmsr_srb_complete(srb, 1);
967123055f0SNathan Whitehorn 				printf("arcmsr%d: scsi id=%d lun=%jx srb='%p' aborted\n"
96822f2616bSXin LI 						, acb->pci_unit, srb->pccb->ccb_h.target_id
969123055f0SNathan Whitehorn 						, (uintmax_t)srb->pccb->ccb_h.target_lun, srb);
970f1c579b1SScott Long 			}
971f1c579b1SScott Long 		}
972f1c579b1SScott Long 		/* enable all outbound interrupt */
97344f05562SScott Long 		arcmsr_enable_allintr(acb, intmask_org);
974f1c579b1SScott Long 	}
97522f2616bSXin LI 	acb->srboutstandingcount = 0;
976ad6d6297SScott Long 	acb->workingsrb_doneindex = 0;
977ad6d6297SScott Long 	acb->workingsrb_startindex = 0;
97822f2616bSXin LI 	acb->pktRequestCount = 0;
97922f2616bSXin LI 	acb->pktReturnCount = 0;
980f1c579b1SScott Long }
981f1c579b1SScott Long /*
982f1c579b1SScott Long **********************************************************************
983f1c579b1SScott Long **********************************************************************
984f1c579b1SScott Long */
98544f05562SScott Long static void arcmsr_build_srb(struct CommandControlBlock *srb,
98644f05562SScott Long 		bus_dma_segment_t *dm_segs, u_int32_t nseg)
987f1c579b1SScott Long {
988ad6d6297SScott Long 	struct ARCMSR_CDB *arcmsr_cdb = &srb->arcmsr_cdb;
989ad6d6297SScott Long 	u_int8_t *psge = (u_int8_t *)&arcmsr_cdb->u;
990ad6d6297SScott Long 	u_int32_t address_lo, address_hi;
991ad6d6297SScott Long 	union ccb *pccb = srb->pccb;
992f1c579b1SScott Long 	struct ccb_scsiio *pcsio = &pccb->csio;
993ad6d6297SScott Long 	u_int32_t arccdbsize = 0x30;
994f1c579b1SScott Long 
995ad6d6297SScott Long 	memset(arcmsr_cdb, 0, sizeof(struct ARCMSR_CDB));
996ad6d6297SScott Long 	arcmsr_cdb->Bus = 0;
997ad6d6297SScott Long 	arcmsr_cdb->TargetID = pccb->ccb_h.target_id;
998ad6d6297SScott Long 	arcmsr_cdb->LUN = pccb->ccb_h.target_lun;
999ad6d6297SScott Long 	arcmsr_cdb->Function = 1;
1000ad6d6297SScott Long 	arcmsr_cdb->CdbLength = (u_int8_t)pcsio->cdb_len;
10014aa947cbSWarner Losh 	bcopy(scsiio_cdb_ptr(pcsio), arcmsr_cdb->Cdb, pcsio->cdb_len);
1002ad6d6297SScott Long 	if(nseg != 0) {
1003ad6d6297SScott Long 		struct AdapterControlBlock *acb = srb->acb;
1004f1c579b1SScott Long 		bus_dmasync_op_t op;
1005ad6d6297SScott Long 		u_int32_t length, i, cdb_sgcount = 0;
1006f1c579b1SScott Long 
1007ad6d6297SScott Long 		if((pccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
1008ad6d6297SScott Long 			op = BUS_DMASYNC_PREREAD;
1009ad6d6297SScott Long 		} else {
1010ad6d6297SScott Long 			op = BUS_DMASYNC_PREWRITE;
1011ad6d6297SScott Long 			arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_WRITE;
1012ad6d6297SScott Long 			srb->srb_flags |= SRB_FLAG_WRITE;
1013ad6d6297SScott Long 		}
1014ad6d6297SScott Long 		bus_dmamap_sync(acb->dm_segs_dmat, srb->dm_segs_dmamap, op);
1015ad6d6297SScott Long 		for(i=0; i < nseg; i++) {
1016f1c579b1SScott Long 			/* Get the physical address of the current data pointer */
1017ad6d6297SScott Long 			length = arcmsr_htole32(dm_segs[i].ds_len);
1018ad6d6297SScott Long 			address_lo = arcmsr_htole32(dma_addr_lo32(dm_segs[i].ds_addr));
1019ad6d6297SScott Long 			address_hi = arcmsr_htole32(dma_addr_hi32(dm_segs[i].ds_addr));
1020ad6d6297SScott Long 			if(address_hi == 0) {
1021ad6d6297SScott Long 				struct SG32ENTRY *pdma_sg = (struct SG32ENTRY *)psge;
1022f1c579b1SScott Long 				pdma_sg->address = address_lo;
1023f1c579b1SScott Long 				pdma_sg->length = length;
1024ad6d6297SScott Long 				psge += sizeof(struct SG32ENTRY);
1025ad6d6297SScott Long 				arccdbsize += sizeof(struct SG32ENTRY);
1026ad6d6297SScott Long 			} else {
1027ad6d6297SScott Long 				u_int32_t sg64s_size = 0, tmplength = length;
1028f1c579b1SScott Long 
1029ad6d6297SScott Long 				while(1) {
1030ad6d6297SScott Long 					u_int64_t span4G, length0;
1031ad6d6297SScott Long 					struct SG64ENTRY *pdma_sg = (struct SG64ENTRY *)psge;
1032f1c579b1SScott Long 
1033ad6d6297SScott Long 					span4G = (u_int64_t)address_lo + tmplength;
1034f1c579b1SScott Long 					pdma_sg->addresshigh = address_hi;
1035f1c579b1SScott Long 					pdma_sg->address = address_lo;
1036ad6d6297SScott Long 					if(span4G > 0x100000000) {
1037f1c579b1SScott Long 						/*see if cross 4G boundary*/
1038f1c579b1SScott Long 						length0 = 0x100000000-address_lo;
1039ad6d6297SScott Long 						pdma_sg->length = (u_int32_t)length0 | IS_SG64_ADDR;
1040f1c579b1SScott Long 						address_hi = address_hi+1;
1041f1c579b1SScott Long 						address_lo = 0;
1042ad6d6297SScott Long 						tmplength = tmplength - (u_int32_t)length0;
1043ad6d6297SScott Long 						sg64s_size += sizeof(struct SG64ENTRY);
1044ad6d6297SScott Long 						psge += sizeof(struct SG64ENTRY);
1045f1c579b1SScott Long 						cdb_sgcount++;
1046ad6d6297SScott Long 					} else {
1047f1c579b1SScott Long 						pdma_sg->length = tmplength | IS_SG64_ADDR;
1048ad6d6297SScott Long 						sg64s_size += sizeof(struct SG64ENTRY);
1049ad6d6297SScott Long 						psge += sizeof(struct SG64ENTRY);
1050f1c579b1SScott Long 						break;
1051f1c579b1SScott Long 					}
1052f1c579b1SScott Long 				}
1053f1c579b1SScott Long 				arccdbsize += sg64s_size;
1054f1c579b1SScott Long 			}
1055f1c579b1SScott Long 			cdb_sgcount++;
1056f1c579b1SScott Long 		}
1057ad6d6297SScott Long 		arcmsr_cdb->sgcount = (u_int8_t)cdb_sgcount;
1058ad6d6297SScott Long 		arcmsr_cdb->DataLength = pcsio->dxfer_len;
1059ad6d6297SScott Long 		if( arccdbsize > 256) {
1060ad6d6297SScott Long 			arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_SGL_BSIZE;
1061f1c579b1SScott Long 		}
1062d74001adSXin LI 	} else {
1063d74001adSXin LI 		arcmsr_cdb->DataLength = 0;
1064f1c579b1SScott Long 	}
1065d74001adSXin LI 	srb->arc_cdb_size = arccdbsize;
10667a7bc959SXin LI 	arcmsr_cdb->msgPages = (arccdbsize/256) + ((arccdbsize % 256) ? 1 : 0);
1067f1c579b1SScott Long }
1068f1c579b1SScott Long /*
1069f1c579b1SScott Long **************************************************************************
1070f1c579b1SScott Long **************************************************************************
1071f1c579b1SScott Long */
1072ad6d6297SScott Long static void arcmsr_post_srb(struct AdapterControlBlock *acb, struct CommandControlBlock *srb)
1073f1c579b1SScott Long {
10747a7bc959SXin LI 	u_int32_t cdb_phyaddr_low = (u_int32_t) srb->cdb_phyaddr_low;
1075ad6d6297SScott Long 	struct ARCMSR_CDB *arcmsr_cdb = (struct ARCMSR_CDB *)&srb->arcmsr_cdb;
1076f1c579b1SScott Long 
1077d74001adSXin LI 	bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, (srb->srb_flags & SRB_FLAG_WRITE) ? BUS_DMASYNC_POSTWRITE:BUS_DMASYNC_POSTREAD);
1078ad6d6297SScott Long 	atomic_add_int(&acb->srboutstandingcount, 1);
107922f2616bSXin LI 	srb->srb_state = ARCMSR_SRB_START;
1080d74001adSXin LI 
108144f05562SScott Long 	switch (acb->adapter_type) {
108244f05562SScott Long 	case ACB_ADAPTER_TYPE_A: {
1083ad6d6297SScott Long 			if(arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) {
10847a7bc959SXin LI 				CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_queueport, cdb_phyaddr_low|ARCMSR_SRBPOST_FLAG_SGL_BSIZE);
1085ad6d6297SScott Long 			} else {
10867a7bc959SXin LI 				CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_queueport, cdb_phyaddr_low);
108744f05562SScott Long 			}
108844f05562SScott Long 		}
108944f05562SScott Long 		break;
109044f05562SScott Long 	case ACB_ADAPTER_TYPE_B: {
109144f05562SScott Long 			struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
109244f05562SScott Long 			int ending_index, index;
109344f05562SScott Long 
109444f05562SScott Long 			index = phbbmu->postq_index;
109544f05562SScott Long 			ending_index = ((index+1) % ARCMSR_MAX_HBB_POSTQUEUE);
109644f05562SScott Long 			phbbmu->post_qbuffer[ending_index] = 0;
109744f05562SScott Long 			if(arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) {
10987a7bc959SXin LI 				phbbmu->post_qbuffer[index] = cdb_phyaddr_low | ARCMSR_SRBPOST_FLAG_SGL_BSIZE;
109944f05562SScott Long 			} else {
11007a7bc959SXin LI 				phbbmu->post_qbuffer[index] = cdb_phyaddr_low;
110144f05562SScott Long 			}
110244f05562SScott Long 			index++;
110344f05562SScott Long 			index %= ARCMSR_MAX_HBB_POSTQUEUE;     /*if last index number set it to 0 */
110444f05562SScott Long 			phbbmu->postq_index = index;
1105b23a1998SXin LI 			WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_CDB_POSTED);
1106d74001adSXin LI 		}
1107d74001adSXin LI 		break;
11087a7bc959SXin LI 	case ACB_ADAPTER_TYPE_C: {
1109d74001adSXin LI 			u_int32_t ccb_post_stamp, arc_cdb_size, cdb_phyaddr_hi32;
1110d74001adSXin LI 
1111d74001adSXin LI 			arc_cdb_size = (srb->arc_cdb_size > 0x300) ? 0x300 : srb->arc_cdb_size;
11127a7bc959SXin LI 			ccb_post_stamp = (cdb_phyaddr_low | ((arc_cdb_size-1) >> 6) | 1);
1113d74001adSXin LI 			cdb_phyaddr_hi32 = acb->srb_phyaddr.B.phyadd_high;
1114d74001adSXin LI 			if(cdb_phyaddr_hi32)
1115d74001adSXin LI 			{
1116d74001adSXin LI 				CHIP_REG_WRITE32(HBC_MessageUnit,0,inbound_queueport_high, cdb_phyaddr_hi32);
1117d74001adSXin LI 				CHIP_REG_WRITE32(HBC_MessageUnit,0,inbound_queueport_low, ccb_post_stamp);
1118d74001adSXin LI 			}
1119d74001adSXin LI 			else
1120d74001adSXin LI 			{
1121d74001adSXin LI 				CHIP_REG_WRITE32(HBC_MessageUnit,0,inbound_queueport_low, ccb_post_stamp);
1122d74001adSXin LI 			}
112344f05562SScott Long 		}
112444f05562SScott Long 		break;
11257a7bc959SXin LI 	case ACB_ADAPTER_TYPE_D: {
11267a7bc959SXin LI 			struct HBD_MessageUnit0 *phbdmu = (struct HBD_MessageUnit0 *)acb->pmu;
11277a7bc959SXin LI 			u_int16_t index_stripped;
11287a7bc959SXin LI 			u_int16_t postq_index;
11297a7bc959SXin LI 			struct InBound_SRB *pinbound_srb;
11307a7bc959SXin LI 
11317a7bc959SXin LI 			ARCMSR_LOCK_ACQUIRE(&acb->postDone_lock);
11327a7bc959SXin LI 			postq_index = phbdmu->postq_index;
11337a7bc959SXin LI 			pinbound_srb = (struct InBound_SRB *)&phbdmu->post_qbuffer[postq_index & 0xFF];
11347a7bc959SXin LI 			pinbound_srb->addressHigh = srb->cdb_phyaddr_high;
11357a7bc959SXin LI 			pinbound_srb->addressLow = srb->cdb_phyaddr_low;
11367a7bc959SXin LI 			pinbound_srb->length = srb->arc_cdb_size >> 2;
11377a7bc959SXin LI 			arcmsr_cdb->Context = srb->cdb_phyaddr_low;
11387a7bc959SXin LI 			if (postq_index & 0x4000) {
11397a7bc959SXin LI 				index_stripped = postq_index & 0xFF;
11407a7bc959SXin LI 				index_stripped += 1;
11417a7bc959SXin LI 				index_stripped %= ARCMSR_MAX_HBD_POSTQUEUE;
11427a7bc959SXin LI 				phbdmu->postq_index = index_stripped ? (index_stripped | 0x4000) : index_stripped;
11437a7bc959SXin LI 			} else {
11447a7bc959SXin LI 				index_stripped = postq_index;
11457a7bc959SXin LI 				index_stripped += 1;
11467a7bc959SXin LI 				index_stripped %= ARCMSR_MAX_HBD_POSTQUEUE;
11477a7bc959SXin LI 				phbdmu->postq_index = index_stripped ? index_stripped : (index_stripped | 0x4000);
11487a7bc959SXin LI 			}
11497a7bc959SXin LI 			CHIP_REG_WRITE32(HBD_MessageUnit, 0, inboundlist_write_pointer, postq_index);
11507a7bc959SXin LI 			ARCMSR_LOCK_RELEASE(&acb->postDone_lock);
11517a7bc959SXin LI 		}
11527a7bc959SXin LI 		break;
1153a1103e04SXin LI 	case ACB_ADAPTER_TYPE_E: {
1154a1103e04SXin LI 			u_int32_t ccb_post_stamp, arc_cdb_size;
1155a1103e04SXin LI 
1156a1103e04SXin LI 			arc_cdb_size = (srb->arc_cdb_size > 0x300) ? 0x300 : srb->arc_cdb_size;
1157a1103e04SXin LI 			ccb_post_stamp = (srb->smid | ((arc_cdb_size-1) >> 6));
1158a1103e04SXin LI 			CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_queueport_high, 0);
1159a1103e04SXin LI 			CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_queueport_low, ccb_post_stamp);
1160a1103e04SXin LI 		}
1161a1103e04SXin LI 		break;
1162fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_F: {
1163fa42a0bfSXin LI 			u_int32_t ccb_post_stamp, arc_cdb_size;
1164fa42a0bfSXin LI 
1165fa42a0bfSXin LI 			if (srb->arc_cdb_size <= 0x300)
1166fa42a0bfSXin LI 				arc_cdb_size = (srb->arc_cdb_size - 1) >> 6 | 1;
1167438b5532SXin LI 			else {
1168438b5532SXin LI 				arc_cdb_size = ((srb->arc_cdb_size + 0xff) >> 8) + 2;
1169438b5532SXin LI 				if (arc_cdb_size > 0xF)
1170438b5532SXin LI 					arc_cdb_size = 0xF;
1171438b5532SXin LI 				arc_cdb_size = (arc_cdb_size << 1) | 1;
1172438b5532SXin LI 			}
1173fa42a0bfSXin LI 			ccb_post_stamp = (srb->smid | arc_cdb_size);
1174fa42a0bfSXin LI 			CHIP_REG_WRITE32(HBF_MessageUnit, 0, inbound_queueport_high, 0);
1175fa42a0bfSXin LI 			CHIP_REG_WRITE32(HBF_MessageUnit, 0, inbound_queueport_low, ccb_post_stamp);
1176fa42a0bfSXin LI 		}
1177fa42a0bfSXin LI 		break;
1178f1c579b1SScott Long 	}
1179f1c579b1SScott Long }
1180f1c579b1SScott Long /*
118144f05562SScott Long ************************************************************************
118244f05562SScott Long ************************************************************************
118344f05562SScott Long */
118444f05562SScott Long static struct QBUFFER *arcmsr_get_iop_rqbuffer( struct AdapterControlBlock *acb)
118544f05562SScott Long {
118644f05562SScott Long 	struct QBUFFER *qbuffer=NULL;
118744f05562SScott Long 
118844f05562SScott Long 	switch (acb->adapter_type) {
118944f05562SScott Long 	case ACB_ADAPTER_TYPE_A: {
119044f05562SScott Long 			struct HBA_MessageUnit *phbamu = (struct HBA_MessageUnit *)acb->pmu;
119144f05562SScott Long 
119244f05562SScott Long 			qbuffer = (struct QBUFFER *)&phbamu->message_rbuffer;
119344f05562SScott Long 		}
119444f05562SScott Long 		break;
119544f05562SScott Long 	case ACB_ADAPTER_TYPE_B: {
119644f05562SScott Long 			struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
119744f05562SScott Long 
119844f05562SScott Long 			qbuffer = (struct QBUFFER *)&phbbmu->hbb_rwbuffer->message_rbuffer;
119944f05562SScott Long 		}
120044f05562SScott Long 		break;
1201d74001adSXin LI 	case ACB_ADAPTER_TYPE_C: {
1202d74001adSXin LI 			struct HBC_MessageUnit *phbcmu = (struct HBC_MessageUnit *)acb->pmu;
1203d74001adSXin LI 
1204d74001adSXin LI 			qbuffer = (struct QBUFFER *)&phbcmu->message_rbuffer;
1205d74001adSXin LI 		}
1206d74001adSXin LI 		break;
12077a7bc959SXin LI 	case ACB_ADAPTER_TYPE_D: {
12087a7bc959SXin LI 			struct HBD_MessageUnit0 *phbdmu = (struct HBD_MessageUnit0 *)acb->pmu;
12097a7bc959SXin LI 
12107a7bc959SXin LI 			qbuffer = (struct QBUFFER *)&phbdmu->phbdmu->message_rbuffer;
12117a7bc959SXin LI 		}
12127a7bc959SXin LI 		break;
1213a1103e04SXin LI 	case ACB_ADAPTER_TYPE_E: {
1214a1103e04SXin LI 			struct HBE_MessageUnit *phbcmu = (struct HBE_MessageUnit *)acb->pmu;
1215a1103e04SXin LI 
1216a1103e04SXin LI 			qbuffer = (struct QBUFFER *)&phbcmu->message_rbuffer;
1217a1103e04SXin LI 		}
1218a1103e04SXin LI 		break;
1219fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_F:
1220fa42a0bfSXin LI 		qbuffer = (struct QBUFFER *)acb->message_rbuffer;
1221fa42a0bfSXin LI 		break;
122244f05562SScott Long 	}
122344f05562SScott Long 	return(qbuffer);
122444f05562SScott Long }
122544f05562SScott Long /*
122644f05562SScott Long ************************************************************************
122744f05562SScott Long ************************************************************************
122844f05562SScott Long */
122944f05562SScott Long static struct QBUFFER *arcmsr_get_iop_wqbuffer( struct AdapterControlBlock *acb)
123044f05562SScott Long {
123144f05562SScott Long 	struct QBUFFER *qbuffer = NULL;
123244f05562SScott Long 
123344f05562SScott Long 	switch (acb->adapter_type) {
123444f05562SScott Long 	case ACB_ADAPTER_TYPE_A: {
123544f05562SScott Long 			struct HBA_MessageUnit *phbamu = (struct HBA_MessageUnit *)acb->pmu;
123644f05562SScott Long 
123744f05562SScott Long 			qbuffer = (struct QBUFFER *)&phbamu->message_wbuffer;
123844f05562SScott Long 		}
123944f05562SScott Long 		break;
124044f05562SScott Long 	case ACB_ADAPTER_TYPE_B: {
124144f05562SScott Long 			struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
124244f05562SScott Long 
124344f05562SScott Long 			qbuffer = (struct QBUFFER *)&phbbmu->hbb_rwbuffer->message_wbuffer;
124444f05562SScott Long 		}
124544f05562SScott Long 		break;
1246d74001adSXin LI 	case ACB_ADAPTER_TYPE_C: {
1247d74001adSXin LI 			struct HBC_MessageUnit *phbcmu = (struct HBC_MessageUnit *)acb->pmu;
1248d74001adSXin LI 
1249d74001adSXin LI 			qbuffer = (struct QBUFFER *)&phbcmu->message_wbuffer;
1250d74001adSXin LI 		}
1251d74001adSXin LI 		break;
12527a7bc959SXin LI 	case ACB_ADAPTER_TYPE_D: {
12537a7bc959SXin LI 			struct HBD_MessageUnit0 *phbdmu = (struct HBD_MessageUnit0 *)acb->pmu;
12547a7bc959SXin LI 
12557a7bc959SXin LI 			qbuffer = (struct QBUFFER *)&phbdmu->phbdmu->message_wbuffer;
12567a7bc959SXin LI 		}
12577a7bc959SXin LI 		break;
1258a1103e04SXin LI 	case ACB_ADAPTER_TYPE_E: {
1259a1103e04SXin LI 			struct HBE_MessageUnit *phbcmu = (struct HBE_MessageUnit *)acb->pmu;
1260a1103e04SXin LI 
1261a1103e04SXin LI 			qbuffer = (struct QBUFFER *)&phbcmu->message_wbuffer;
1262a1103e04SXin LI 		}
1263a1103e04SXin LI 		break;
1264fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_F:
1265fa42a0bfSXin LI 		qbuffer = (struct QBUFFER *)acb->message_wbuffer;
1266fa42a0bfSXin LI 		break;
126744f05562SScott Long 	}
126844f05562SScott Long 	return(qbuffer);
126944f05562SScott Long }
127044f05562SScott Long /*
127144f05562SScott Long **************************************************************************
127244f05562SScott Long **************************************************************************
127344f05562SScott Long */
127444f05562SScott Long static void arcmsr_iop_message_read(struct AdapterControlBlock *acb)
127544f05562SScott Long {
127644f05562SScott Long 	switch (acb->adapter_type) {
127744f05562SScott Long 	case ACB_ADAPTER_TYPE_A: {
127844f05562SScott Long 			/* let IOP know data has been read */
1279d74001adSXin LI 			CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK);
128044f05562SScott Long 		}
128144f05562SScott Long 		break;
128244f05562SScott Long 	case ACB_ADAPTER_TYPE_B: {
1283b23a1998SXin LI 			struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
128444f05562SScott Long 			/* let IOP know data has been read */
1285b23a1998SXin LI 			WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_READ_OK);
128644f05562SScott Long 		}
128744f05562SScott Long 		break;
1288d74001adSXin LI 	case ACB_ADAPTER_TYPE_C: {
1289d74001adSXin LI 			/* let IOP know data has been read */
1290d74001adSXin LI 			CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK);
1291d74001adSXin LI 		}
12927a7bc959SXin LI 		break;
12937a7bc959SXin LI 	case ACB_ADAPTER_TYPE_D: {
12947a7bc959SXin LI 			/* let IOP know data has been read */
12957a7bc959SXin LI 			CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_doorbell, ARCMSR_HBDMU_DRV2IOP_DATA_OUT_READ);
12967a7bc959SXin LI 		}
12977a7bc959SXin LI 		break;
1298fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_E:
1299fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_F: {
1300a1103e04SXin LI 			/* let IOP know data has been read */
1301a1103e04SXin LI 			acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_DATA_READ_OK;
1302a1103e04SXin LI 			CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
1303a1103e04SXin LI 		}
1304a1103e04SXin LI 		break;
130544f05562SScott Long 	}
130644f05562SScott Long }
130744f05562SScott Long /*
130844f05562SScott Long **************************************************************************
130944f05562SScott Long **************************************************************************
131044f05562SScott Long */
131144f05562SScott Long static void arcmsr_iop_message_wrote(struct AdapterControlBlock *acb)
131244f05562SScott Long {
131344f05562SScott Long 	switch (acb->adapter_type) {
131444f05562SScott Long 	case ACB_ADAPTER_TYPE_A: {
131544f05562SScott Long 			/*
131644f05562SScott Long 			** push inbound doorbell tell iop, driver data write ok
131744f05562SScott Long 			** and wait reply on next hwinterrupt for next Qbuffer post
131844f05562SScott Long 			*/
1319d74001adSXin LI 			CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK);
132044f05562SScott Long 		}
132144f05562SScott Long 		break;
132244f05562SScott Long 	case ACB_ADAPTER_TYPE_B: {
1323b23a1998SXin LI 			struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
132444f05562SScott Long 			/*
132544f05562SScott Long 			** push inbound doorbell tell iop, driver data write ok
132644f05562SScott Long 			** and wait reply on next hwinterrupt for next Qbuffer post
132744f05562SScott Long 			*/
1328b23a1998SXin LI 			WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_WRITE_OK);
1329d74001adSXin LI 		}
1330d74001adSXin LI 		break;
1331d74001adSXin LI 	case ACB_ADAPTER_TYPE_C: {
1332d74001adSXin LI 			/*
1333d74001adSXin LI 			** push inbound doorbell tell iop, driver data write ok
1334d74001adSXin LI 			** and wait reply on next hwinterrupt for next Qbuffer post
1335d74001adSXin LI 			*/
1336d74001adSXin LI 			CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_DATA_WRITE_OK);
133744f05562SScott Long 		}
133844f05562SScott Long 		break;
13397a7bc959SXin LI 	case ACB_ADAPTER_TYPE_D: {
134044f05562SScott Long 			/*
13417a7bc959SXin LI 			** push inbound doorbell tell iop, driver data write ok
13427a7bc959SXin LI 			** and wait reply on next hwinterrupt for next Qbuffer post
1343f1c579b1SScott Long 			*/
13447a7bc959SXin LI 			CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_doorbell, ARCMSR_HBDMU_DRV2IOP_DATA_IN_READY);
1345f1c579b1SScott Long 		}
13467a7bc959SXin LI 		break;
1347fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_E:
1348fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_F: {
1349a1103e04SXin LI 			/*
1350a1103e04SXin LI 			** push inbound doorbell tell iop, driver data write ok
1351a1103e04SXin LI 			** and wait reply on next hwinterrupt for next Qbuffer post
1352a1103e04SXin LI 			*/
1353a1103e04SXin LI 			acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_DATA_WRITE_OK;
1354a1103e04SXin LI 			CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
1355a1103e04SXin LI 		}
1356a1103e04SXin LI 		break;
1357ad6d6297SScott Long 	}
1358f1c579b1SScott Long }
1359f1c579b1SScott Long /*
1360f1c579b1SScott Long ************************************************************************
1361f1c579b1SScott Long ************************************************************************
1362f1c579b1SScott Long */
136344f05562SScott Long static void arcmsr_stop_hba_bgrb(struct AdapterControlBlock *acb)
1364f1c579b1SScott Long {
1365ad6d6297SScott Long 	acb->acb_flags &= ~ACB_F_MSG_START_BGRB;
136644f05562SScott Long 	CHIP_REG_WRITE32(HBA_MessageUnit,
136744f05562SScott Long 		0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB);
136844f05562SScott Long 	if(!arcmsr_hba_wait_msgint_ready(acb)) {
1369*2f7e72bdSMustafa Ateş Uzun 		printf("arcmsr%d: wait 'stop adapter background rebuild' timeout \n"
1370ad6d6297SScott Long 			, acb->pci_unit);
1371ad6d6297SScott Long 	}
1372f1c579b1SScott Long }
1373f1c579b1SScott Long /*
1374f1c579b1SScott Long ************************************************************************
1375f1c579b1SScott Long ************************************************************************
1376f1c579b1SScott Long */
137744f05562SScott Long static void arcmsr_stop_hbb_bgrb(struct AdapterControlBlock *acb)
137844f05562SScott Long {
1379b23a1998SXin LI 	struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
138044f05562SScott Long 	acb->acb_flags &= ~ACB_F_MSG_START_BGRB;
1381b23a1998SXin LI 	WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_STOP_BGRB);
138244f05562SScott Long 	if(!arcmsr_hbb_wait_msgint_ready(acb)) {
1383*2f7e72bdSMustafa Ateş Uzun 		printf( "arcmsr%d: wait 'stop adapter background rebuild' timeout \n"
138444f05562SScott Long 			, acb->pci_unit);
138544f05562SScott Long 	}
138644f05562SScott Long }
138744f05562SScott Long /*
138844f05562SScott Long ************************************************************************
138944f05562SScott Long ************************************************************************
139044f05562SScott Long */
1391d74001adSXin LI static void arcmsr_stop_hbc_bgrb(struct AdapterControlBlock *acb)
1392d74001adSXin LI {
1393d74001adSXin LI 	acb->acb_flags &= ~ACB_F_MSG_START_BGRB;
1394d74001adSXin LI 	CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB);
1395d74001adSXin LI 	CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell,ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE);
1396d74001adSXin LI 	if(!arcmsr_hbc_wait_msgint_ready(acb)) {
1397*2f7e72bdSMustafa Ateş Uzun 		printf("arcmsr%d: wait 'stop adapter background rebuild' timeout \n", acb->pci_unit);
1398d74001adSXin LI 	}
1399d74001adSXin LI }
1400d74001adSXin LI /*
1401d74001adSXin LI ************************************************************************
1402d74001adSXin LI ************************************************************************
1403d74001adSXin LI */
14047a7bc959SXin LI static void arcmsr_stop_hbd_bgrb(struct AdapterControlBlock *acb)
14057a7bc959SXin LI {
14067a7bc959SXin LI 	acb->acb_flags &= ~ACB_F_MSG_START_BGRB;
14077a7bc959SXin LI 	CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB);
14087a7bc959SXin LI 	if(!arcmsr_hbd_wait_msgint_ready(acb)) {
1409*2f7e72bdSMustafa Ateş Uzun 		printf("arcmsr%d: wait 'stop adapter background rebuild' timeout \n", acb->pci_unit);
14107a7bc959SXin LI 	}
14117a7bc959SXin LI }
14127a7bc959SXin LI /*
14137a7bc959SXin LI ************************************************************************
14147a7bc959SXin LI ************************************************************************
14157a7bc959SXin LI */
1416a1103e04SXin LI static void arcmsr_stop_hbe_bgrb(struct AdapterControlBlock *acb)
1417a1103e04SXin LI {
1418a1103e04SXin LI 	acb->acb_flags &= ~ACB_F_MSG_START_BGRB;
1419a1103e04SXin LI 	CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB);
1420a1103e04SXin LI 	acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
1421a1103e04SXin LI 	CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
1422a1103e04SXin LI 	if(!arcmsr_hbe_wait_msgint_ready(acb)) {
1423*2f7e72bdSMustafa Ateş Uzun 		printf("arcmsr%d: wait 'stop adapter background rebuild' timeout \n", acb->pci_unit);
1424a1103e04SXin LI 	}
1425a1103e04SXin LI }
1426a1103e04SXin LI /*
1427a1103e04SXin LI ************************************************************************
1428a1103e04SXin LI ************************************************************************
1429a1103e04SXin LI */
143044f05562SScott Long static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb)
143144f05562SScott Long {
143244f05562SScott Long 	switch (acb->adapter_type) {
143344f05562SScott Long 	case ACB_ADAPTER_TYPE_A: {
143444f05562SScott Long 			arcmsr_stop_hba_bgrb(acb);
143544f05562SScott Long 		}
143644f05562SScott Long 		break;
143744f05562SScott Long 	case ACB_ADAPTER_TYPE_B: {
143844f05562SScott Long 			arcmsr_stop_hbb_bgrb(acb);
143944f05562SScott Long 		}
144044f05562SScott Long 		break;
1441d74001adSXin LI 	case ACB_ADAPTER_TYPE_C: {
1442d74001adSXin LI 			arcmsr_stop_hbc_bgrb(acb);
1443d74001adSXin LI 		}
1444d74001adSXin LI 		break;
14457a7bc959SXin LI 	case ACB_ADAPTER_TYPE_D: {
14467a7bc959SXin LI 			arcmsr_stop_hbd_bgrb(acb);
14477a7bc959SXin LI 		}
14487a7bc959SXin LI 		break;
1449fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_E:
1450fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_F: {
1451a1103e04SXin LI 			arcmsr_stop_hbe_bgrb(acb);
1452a1103e04SXin LI 		}
1453a1103e04SXin LI 		break;
145444f05562SScott Long 	}
145544f05562SScott Long }
145644f05562SScott Long /*
145744f05562SScott Long ************************************************************************
145844f05562SScott Long ************************************************************************
145944f05562SScott Long */
1460ad6d6297SScott Long static void arcmsr_poll(struct cam_sim *psim)
1461f1c579b1SScott Long {
1462579ec1a5SScott Long 	struct AdapterControlBlock *acb;
14634e32649fSXin LI 	int	mutex;
1464579ec1a5SScott Long 
1465579ec1a5SScott Long 	acb = (struct AdapterControlBlock *)cam_sim_softc(psim);
14667a7bc959SXin LI 	mutex = mtx_owned(&acb->isr_lock);
14674e32649fSXin LI 	if( mutex == 0 )
14687a7bc959SXin LI 		ARCMSR_LOCK_ACQUIRE(&acb->isr_lock);
1469579ec1a5SScott Long 	arcmsr_interrupt(acb);
14704e32649fSXin LI 	if( mutex == 0 )
14717a7bc959SXin LI 		ARCMSR_LOCK_RELEASE(&acb->isr_lock);
14727a7bc959SXin LI }
14737a7bc959SXin LI /*
14747a7bc959SXin LI **************************************************************************
14757a7bc959SXin LI **************************************************************************
14767a7bc959SXin LI */
147735689395SXin LI static u_int32_t arcmsr_Read_iop_rqbuffer_data_D(struct AdapterControlBlock *acb,
147835689395SXin LI 	struct QBUFFER *prbuffer) {
147935689395SXin LI 	u_int8_t *pQbuffer;
14804d24901aSPedro F. Giffuni 	u_int8_t *buf1 = NULL;
14814d24901aSPedro F. Giffuni 	u_int32_t *iop_data, *buf2 = NULL;
148235689395SXin LI 	u_int32_t iop_len, data_len;
148335689395SXin LI 
148435689395SXin LI 	iop_data = (u_int32_t *)prbuffer->data;
148535689395SXin LI 	iop_len = (u_int32_t)prbuffer->data_len;
148635689395SXin LI 	if ( iop_len > 0 )
148735689395SXin LI 	{
148835689395SXin LI 		buf1 = malloc(128, M_DEVBUF, M_NOWAIT | M_ZERO);
148935689395SXin LI 		buf2 = (u_int32_t *)buf1;
149035689395SXin LI 		if( buf1 == NULL)
149135689395SXin LI 			return (0);
149235689395SXin LI 		data_len = iop_len;
149335689395SXin LI 		while(data_len >= 4)
149435689395SXin LI 		{
149535689395SXin LI 			*buf2++ = *iop_data++;
149635689395SXin LI 			data_len -= 4;
149735689395SXin LI 		}
149835689395SXin LI 		if(data_len)
149935689395SXin LI 			*buf2 = *iop_data;
150035689395SXin LI 		buf2 = (u_int32_t *)buf1;
150135689395SXin LI 	}
150235689395SXin LI 	while (iop_len > 0) {
150335689395SXin LI 		pQbuffer = &acb->rqbuffer[acb->rqbuf_lastindex];
150435689395SXin LI 		*pQbuffer = *buf1;
150535689395SXin LI 		acb->rqbuf_lastindex++;
150635689395SXin LI 		/* if last, index number set it to 0 */
150735689395SXin LI 		acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER;
150835689395SXin LI 		buf1++;
150935689395SXin LI 		iop_len--;
151035689395SXin LI 	}
151135689395SXin LI 	if(buf2)
151235689395SXin LI 		free( (u_int8_t *)buf2, M_DEVBUF);
151335689395SXin LI 	/* let IOP know data has been read */
151435689395SXin LI 	arcmsr_iop_message_read(acb);
151535689395SXin LI 	return (1);
151635689395SXin LI }
151735689395SXin LI /*
151835689395SXin LI **************************************************************************
151935689395SXin LI **************************************************************************
152035689395SXin LI */
152135689395SXin LI static u_int32_t arcmsr_Read_iop_rqbuffer_data(struct AdapterControlBlock *acb,
15227a7bc959SXin LI 	struct QBUFFER *prbuffer) {
15237a7bc959SXin LI 	u_int8_t *pQbuffer;
15247a7bc959SXin LI 	u_int8_t *iop_data;
15257a7bc959SXin LI 	u_int32_t iop_len;
15267a7bc959SXin LI 
1527fc5ef1caSXin LI 	if(acb->adapter_type >= ACB_ADAPTER_TYPE_B) {
152835689395SXin LI 		return(arcmsr_Read_iop_rqbuffer_data_D(acb, prbuffer));
152935689395SXin LI 	}
15307a7bc959SXin LI 	iop_data = (u_int8_t *)prbuffer->data;
15317a7bc959SXin LI 	iop_len = (u_int32_t)prbuffer->data_len;
15327a7bc959SXin LI 	while (iop_len > 0) {
15337a7bc959SXin LI 		pQbuffer = &acb->rqbuffer[acb->rqbuf_lastindex];
15347a7bc959SXin LI 		*pQbuffer = *iop_data;
15357a7bc959SXin LI 		acb->rqbuf_lastindex++;
15367a7bc959SXin LI 		/* if last, index number set it to 0 */
15377a7bc959SXin LI 		acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER;
15387a7bc959SXin LI 		iop_data++;
15397a7bc959SXin LI 		iop_len--;
15407a7bc959SXin LI 	}
15417a7bc959SXin LI 	/* let IOP know data has been read */
15427a7bc959SXin LI 	arcmsr_iop_message_read(acb);
154335689395SXin LI 	return (1);
1544f1c579b1SScott Long }
1545f1c579b1SScott Long /*
154644f05562SScott Long **************************************************************************
154744f05562SScott Long **************************************************************************
15485878cbecSScott Long */
154944f05562SScott Long static void arcmsr_iop2drv_data_wrote_handle(struct AdapterControlBlock *acb)
1550f1c579b1SScott Long {
155144f05562SScott Long 	struct QBUFFER *prbuffer;
15527a7bc959SXin LI 	int my_empty_len;
1553ad6d6297SScott Long 
1554f1c579b1SScott Long 	/*check this iop data if overflow my rqbuffer*/
15557a7bc959SXin LI 	ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
155644f05562SScott Long 	prbuffer = arcmsr_get_iop_rqbuffer(acb);
1557285d85f4S黃清隆 	if (acb->rqbuf_lastindex >= acb->rqbuf_firstindex)
1558285d85f4S黃清隆 		my_empty_len = (ARCMSR_MAX_QBUFFER - 1) - (acb->rqbuf_lastindex - acb->rqbuf_firstindex);
1559285d85f4S黃清隆 	else
1560285d85f4S黃清隆 		my_empty_len = acb->rqbuf_firstindex - acb->rqbuf_lastindex - 1;
15617a7bc959SXin LI 	if(my_empty_len >= prbuffer->data_len) {
156235689395SXin LI 		if(arcmsr_Read_iop_rqbuffer_data(acb, prbuffer) == 0)
156335689395SXin LI 			acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW;
1564ad6d6297SScott Long 	} else {
1565ad6d6297SScott Long 		acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW;
1566f1c579b1SScott Long 	}
15677a7bc959SXin LI 	ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
15687a7bc959SXin LI }
15697a7bc959SXin LI /*
15707a7bc959SXin LI **********************************************************************
15717a7bc959SXin LI **********************************************************************
15727a7bc959SXin LI */
157335689395SXin LI static void arcmsr_Write_data_2iop_wqbuffer_D(struct AdapterControlBlock *acb)
157435689395SXin LI {
157535689395SXin LI 	u_int8_t *pQbuffer;
157635689395SXin LI 	struct QBUFFER *pwbuffer;
15774d24901aSPedro F. Giffuni 	u_int8_t *buf1 = NULL;
15784d24901aSPedro F. Giffuni 	u_int32_t *iop_data, *buf2 = NULL;
157935689395SXin LI 	u_int32_t allxfer_len = 0, data_len;
158035689395SXin LI 
158135689395SXin LI 	if(acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_READ) {
158235689395SXin LI 		buf1 = malloc(128, M_DEVBUF, M_NOWAIT | M_ZERO);
158335689395SXin LI 		buf2 = (u_int32_t *)buf1;
158435689395SXin LI 		if( buf1 == NULL)
158535689395SXin LI 			return;
158635689395SXin LI 
158735689395SXin LI 		acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READ);
158835689395SXin LI 		pwbuffer = arcmsr_get_iop_wqbuffer(acb);
158935689395SXin LI 		iop_data = (u_int32_t *)pwbuffer->data;
159035689395SXin LI 		while((acb->wqbuf_firstindex != acb->wqbuf_lastindex)
159135689395SXin LI 			&& (allxfer_len < 124)) {
159235689395SXin LI 			pQbuffer = &acb->wqbuffer[acb->wqbuf_firstindex];
159335689395SXin LI 			*buf1 = *pQbuffer;
159435689395SXin LI 			acb->wqbuf_firstindex++;
159535689395SXin LI 			acb->wqbuf_firstindex %= ARCMSR_MAX_QBUFFER;
159635689395SXin LI 			buf1++;
159735689395SXin LI 			allxfer_len++;
159835689395SXin LI 		}
159935689395SXin LI 		pwbuffer->data_len = allxfer_len;
160035689395SXin LI 		data_len = allxfer_len;
160135689395SXin LI 		buf1 = (u_int8_t *)buf2;
160235689395SXin LI 		while(data_len >= 4)
160335689395SXin LI 		{
160435689395SXin LI 			*iop_data++ = *buf2++;
160535689395SXin LI 			data_len -= 4;
160635689395SXin LI 		}
160735689395SXin LI 		if(data_len)
160835689395SXin LI 			*iop_data = *buf2;
160935689395SXin LI 		free( buf1, M_DEVBUF);
161035689395SXin LI 		arcmsr_iop_message_wrote(acb);
161135689395SXin LI 	}
161235689395SXin LI }
161335689395SXin LI /*
161435689395SXin LI **********************************************************************
161535689395SXin LI **********************************************************************
161635689395SXin LI */
16177a7bc959SXin LI static void arcmsr_Write_data_2iop_wqbuffer(struct AdapterControlBlock *acb)
16187a7bc959SXin LI {
16197a7bc959SXin LI 	u_int8_t *pQbuffer;
16207a7bc959SXin LI 	struct QBUFFER *pwbuffer;
16217a7bc959SXin LI 	u_int8_t *iop_data;
16227a7bc959SXin LI 	int32_t allxfer_len=0;
16237a7bc959SXin LI 
1624fc5ef1caSXin LI 	if(acb->adapter_type >= ACB_ADAPTER_TYPE_B) {
162535689395SXin LI 		arcmsr_Write_data_2iop_wqbuffer_D(acb);
162635689395SXin LI 		return;
162735689395SXin LI 	}
16287a7bc959SXin LI 	if(acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_READ) {
16297a7bc959SXin LI 		acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READ);
16307a7bc959SXin LI 		pwbuffer = arcmsr_get_iop_wqbuffer(acb);
16317a7bc959SXin LI 		iop_data = (u_int8_t *)pwbuffer->data;
16327a7bc959SXin LI 		while((acb->wqbuf_firstindex != acb->wqbuf_lastindex)
16337a7bc959SXin LI 			&& (allxfer_len < 124)) {
16347a7bc959SXin LI 			pQbuffer = &acb->wqbuffer[acb->wqbuf_firstindex];
16357a7bc959SXin LI 			*iop_data = *pQbuffer;
16367a7bc959SXin LI 			acb->wqbuf_firstindex++;
16377a7bc959SXin LI 			acb->wqbuf_firstindex %= ARCMSR_MAX_QBUFFER;
16387a7bc959SXin LI 			iop_data++;
16397a7bc959SXin LI 			allxfer_len++;
16407a7bc959SXin LI 		}
16417a7bc959SXin LI 		pwbuffer->data_len = allxfer_len;
16427a7bc959SXin LI 		arcmsr_iop_message_wrote(acb);
16437a7bc959SXin LI 	}
1644f1c579b1SScott Long }
1645f1c579b1SScott Long /*
164644f05562SScott Long **************************************************************************
164744f05562SScott Long **************************************************************************
164844f05562SScott Long */
164944f05562SScott Long static void arcmsr_iop2drv_data_read_handle(struct AdapterControlBlock *acb)
165044f05562SScott Long {
16517a7bc959SXin LI 	ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
165244f05562SScott Long 	acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_READ;
165344f05562SScott Long 	/*
165444f05562SScott Long 	*****************************************************************
165544f05562SScott Long 	**   check if there are any mail packages from user space program
165644f05562SScott Long 	**   in my post bag, now is the time to send them into Areca's firmware
165744f05562SScott Long 	*****************************************************************
1658f1c579b1SScott Long 	*/
1659ad6d6297SScott Long 	if(acb->wqbuf_firstindex != acb->wqbuf_lastindex) {
16607a7bc959SXin LI 		arcmsr_Write_data_2iop_wqbuffer(acb);
1661f1c579b1SScott Long 	}
1662ad6d6297SScott Long 	if(acb->wqbuf_firstindex == acb->wqbuf_lastindex) {
1663ad6d6297SScott Long 		acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_CLEARED;
1664f1c579b1SScott Long 	}
16657a7bc959SXin LI 	ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
1666f1c579b1SScott Long }
16677a7bc959SXin LI /*
16687a7bc959SXin LI **************************************************************************
16697a7bc959SXin LI **************************************************************************
16707a7bc959SXin LI */
1671d74001adSXin LI static void arcmsr_rescanLun_cb(struct cam_periph *periph, union ccb *ccb)
1672d74001adSXin LI {
1673d74001adSXin LI /*
1674d74001adSXin LI 	if (ccb->ccb_h.status != CAM_REQ_CMP)
16757a7bc959SXin LI 		printf("arcmsr_rescanLun_cb: Rescan Target=%x, lun=%x,"
16767a7bc959SXin LI 			"failure status=%x\n", ccb->ccb_h.target_id,
16777a7bc959SXin LI 			ccb->ccb_h.target_lun, ccb->ccb_h.status);
1678d74001adSXin LI 	else
1679d74001adSXin LI 		printf("arcmsr_rescanLun_cb: Rescan lun successfully!\n");
1680d74001adSXin LI */
1681d74001adSXin LI 	xpt_free_path(ccb->ccb_h.path);
1682d74001adSXin LI 	xpt_free_ccb(ccb);
1683d74001adSXin LI }
1684d74001adSXin LI 
1685d74001adSXin LI static void	arcmsr_rescan_lun(struct AdapterControlBlock *acb, int target, int lun)
1686d74001adSXin LI {
1687d74001adSXin LI 	struct cam_path     *path;
1688d74001adSXin LI 	union ccb           *ccb;
1689d74001adSXin LI 
1690d74001adSXin LI 	if ((ccb = (union ccb *)xpt_alloc_ccb_nowait()) == NULL)
1691d74001adSXin LI 		return;
1692abfdbca9SXin LI 	if (xpt_create_path(&path, NULL, cam_sim_path(acb->psim), target, lun) != CAM_REQ_CMP)
1693d74001adSXin LI 	{
1694d74001adSXin LI 		xpt_free_ccb(ccb);
1695d74001adSXin LI 		return;
1696d74001adSXin LI 	}
1697d74001adSXin LI /*	printf("arcmsr_rescan_lun: Rescan Target=%x, Lun=%x\n", target, lun); */
1698d74001adSXin LI 	xpt_setup_ccb(&ccb->ccb_h, path, 5);
1699d74001adSXin LI 	ccb->ccb_h.func_code = XPT_SCAN_LUN;
1700d74001adSXin LI 	ccb->ccb_h.cbfcnp = arcmsr_rescanLun_cb;
1701d74001adSXin LI 	ccb->crcn.flags = CAM_FLAG_NONE;
1702d74001adSXin LI 	xpt_action(ccb);
1703d74001adSXin LI }
1704d74001adSXin LI 
1705d74001adSXin LI static void arcmsr_abort_dr_ccbs(struct AdapterControlBlock *acb, int target, int lun)
1706d74001adSXin LI {
1707d74001adSXin LI 	struct CommandControlBlock *srb;
1708d74001adSXin LI 	u_int32_t intmask_org;
1709d74001adSXin LI 	int i;
1710d74001adSXin LI 
1711d74001adSXin LI 	/* disable all outbound interrupts */
1712d74001adSXin LI 	intmask_org = arcmsr_disable_allintr(acb);
1713d74001adSXin LI 	for (i = 0; i < ARCMSR_MAX_FREESRB_NUM; i++)
1714d74001adSXin LI 	{
1715d74001adSXin LI 		srb = acb->psrb_pool[i];
171622f2616bSXin LI 		if (srb->srb_state == ARCMSR_SRB_START)
1717d74001adSXin LI 		{
1718d74001adSXin LI 			if((target == srb->pccb->ccb_h.target_id) && (lun == srb->pccb->ccb_h.target_lun))
1719d74001adSXin LI 			{
172022f2616bSXin LI 				srb->srb_state = ARCMSR_SRB_ABORTED;
1721d74001adSXin LI 				srb->pccb->ccb_h.status |= CAM_REQ_ABORTED;
1722d74001adSXin LI 				arcmsr_srb_complete(srb, 1);
172322f2616bSXin LI 				printf("arcmsr%d: abort scsi id %d lun %d srb=%p \n", acb->pci_unit, target, lun, srb);
1724d74001adSXin LI 			}
1725d74001adSXin LI 		}
1726d74001adSXin LI 	}
1727d74001adSXin LI 	/* enable outbound Post Queue, outbound doorbell Interrupt */
1728d74001adSXin LI 	arcmsr_enable_allintr(acb, intmask_org);
1729d74001adSXin LI }
1730d74001adSXin LI /*
1731d74001adSXin LI **************************************************************************
1732d74001adSXin LI **************************************************************************
1733d74001adSXin LI */
1734d74001adSXin LI static void arcmsr_dr_handle(struct AdapterControlBlock *acb) {
1735d74001adSXin LI 	u_int32_t	devicemap;
1736d74001adSXin LI 	u_int32_t	target, lun;
1737d74001adSXin LI 	u_int32_t	deviceMapCurrent[4]={0};
1738d74001adSXin LI 	u_int8_t	*pDevMap;
1739d74001adSXin LI 
1740d74001adSXin LI 	switch (acb->adapter_type) {
1741d74001adSXin LI 	case ACB_ADAPTER_TYPE_A:
1742d74001adSXin LI 		devicemap = offsetof(struct HBA_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
1743d74001adSXin LI 		for (target = 0; target < 4; target++)
1744d74001adSXin LI 		{
1745d74001adSXin LI 			deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], acb->bhandle[0],  devicemap);
1746d74001adSXin LI 			devicemap += 4;
1747d74001adSXin LI 		}
1748d74001adSXin LI 		break;
1749d74001adSXin LI 
1750d74001adSXin LI 	case ACB_ADAPTER_TYPE_B:
1751d74001adSXin LI 		devicemap = offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
1752d74001adSXin LI 		for (target = 0; target < 4; target++)
1753d74001adSXin LI 		{
1754d74001adSXin LI 			deviceMapCurrent[target]=bus_space_read_4(acb->btag[1], acb->bhandle[1],  devicemap);
1755d74001adSXin LI 			devicemap += 4;
1756d74001adSXin LI 		}
1757d74001adSXin LI 		break;
1758d74001adSXin LI 
1759d74001adSXin LI 	case ACB_ADAPTER_TYPE_C:
1760d74001adSXin LI 		devicemap = offsetof(struct HBC_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
1761d74001adSXin LI 		for (target = 0; target < 4; target++)
1762d74001adSXin LI 		{
1763d74001adSXin LI 			deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], acb->bhandle[0],  devicemap);
1764d74001adSXin LI 			devicemap += 4;
1765d74001adSXin LI 		}
1766d74001adSXin LI 		break;
17677a7bc959SXin LI 	case ACB_ADAPTER_TYPE_D:
17687a7bc959SXin LI 		devicemap = offsetof(struct HBD_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
17697a7bc959SXin LI 		for (target = 0; target < 4; target++)
17707a7bc959SXin LI 		{
17717a7bc959SXin LI 			deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], acb->bhandle[0],  devicemap);
17727a7bc959SXin LI 			devicemap += 4;
17737a7bc959SXin LI 		}
17747a7bc959SXin LI 		break;
1775a1103e04SXin LI 	case ACB_ADAPTER_TYPE_E:
1776a1103e04SXin LI 		devicemap = offsetof(struct HBE_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
1777a1103e04SXin LI 		for (target = 0; target < 4; target++)
1778a1103e04SXin LI 		{
1779a1103e04SXin LI 			deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], acb->bhandle[0],  devicemap);
1780a1103e04SXin LI 			devicemap += 4;
1781a1103e04SXin LI 		}
1782a1103e04SXin LI 		break;
1783fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_F:
1784fa42a0bfSXin LI 		devicemap = ARCMSR_FW_DEVMAP_OFFSET;
1785fa42a0bfSXin LI 		for (target = 0; target < 4; target++)
1786fa42a0bfSXin LI 		{
1787fa42a0bfSXin LI 			deviceMapCurrent[target] = acb->msgcode_rwbuffer[devicemap];
1788fa42a0bfSXin LI 			devicemap += 1;
1789fa42a0bfSXin LI 		}
1790fa42a0bfSXin LI 		break;
1791d74001adSXin LI 	}
1792dac36688SXin LI 
1793d74001adSXin LI 	if(acb->acb_flags & ACB_F_BUS_HANG_ON)
1794d74001adSXin LI 	{
1795d74001adSXin LI 		acb->acb_flags &= ~ACB_F_BUS_HANG_ON;
1796d74001adSXin LI 	}
1797d74001adSXin LI 	/*
1798d74001adSXin LI 	** adapter posted CONFIG message
1799d74001adSXin LI 	** copy the new map, note if there are differences with the current map
1800d74001adSXin LI 	*/
1801d74001adSXin LI 	pDevMap = (u_int8_t *)&deviceMapCurrent[0];
1802d74001adSXin LI 	for (target = 0; target < ARCMSR_MAX_TARGETID - 1; target++)
1803d74001adSXin LI 	{
1804d74001adSXin LI 		if (*pDevMap != acb->device_map[target])
1805d74001adSXin LI 		{
1806d74001adSXin LI 			u_int8_t difference, bit_check;
1807d74001adSXin LI 
1808d74001adSXin LI 			difference = *pDevMap ^ acb->device_map[target];
1809d74001adSXin LI 			for(lun=0; lun < ARCMSR_MAX_TARGETLUN; lun++)
1810d74001adSXin LI 			{
1811d74001adSXin LI 				bit_check = (1 << lun);		/*check bit from 0....31*/
1812d74001adSXin LI 				if(difference & bit_check)
1813d74001adSXin LI 				{
1814d74001adSXin LI 					if(acb->device_map[target] & bit_check)
1815d74001adSXin LI 					{/* unit departed */
1816d74001adSXin LI 						printf("arcmsr_dr_handle: Target=%x, lun=%x, GONE!!!\n",target,lun);
1817d74001adSXin LI 						arcmsr_abort_dr_ccbs(acb, target, lun);
1818d74001adSXin LI 						arcmsr_rescan_lun(acb, target, lun);
1819d74001adSXin LI 						acb->devstate[target][lun] = ARECA_RAID_GONE;
1820d74001adSXin LI 					}
1821d74001adSXin LI 					else
1822d74001adSXin LI 					{/* unit arrived */
182322f2616bSXin LI 						printf("arcmsr_dr_handle: Target=%x, lun=%x, Plug-IN!!!\n",target,lun);
1824d74001adSXin LI 						arcmsr_rescan_lun(acb, target, lun);
1825d74001adSXin LI 						acb->devstate[target][lun] = ARECA_RAID_GOOD;
1826d74001adSXin LI 					}
1827d74001adSXin LI 				}
1828d74001adSXin LI 			}
1829d74001adSXin LI /*			printf("arcmsr_dr_handle: acb->device_map[%x]=0x%x, deviceMapCurrent[%x]=%x\n",target,acb->device_map[target],target,*pDevMap); */
1830d74001adSXin LI 			acb->device_map[target] = *pDevMap;
1831d74001adSXin LI 		}
1832d74001adSXin LI 		pDevMap++;
1833d74001adSXin LI 	}
1834d74001adSXin LI }
1835d74001adSXin LI /*
1836d74001adSXin LI **************************************************************************
1837d74001adSXin LI **************************************************************************
1838d74001adSXin LI */
1839d74001adSXin LI static void arcmsr_hba_message_isr(struct AdapterControlBlock *acb) {
1840d74001adSXin LI 	u_int32_t outbound_message;
1841d74001adSXin LI 
1842d74001adSXin LI 	CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, ARCMSR_MU_OUTBOUND_MESSAGE0_INT);
1843d74001adSXin LI 	outbound_message = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[0]);
1844d74001adSXin LI 	if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG)
1845d74001adSXin LI 		arcmsr_dr_handle( acb );
1846d74001adSXin LI }
1847d74001adSXin LI /*
1848d74001adSXin LI **************************************************************************
1849d74001adSXin LI **************************************************************************
1850d74001adSXin LI */
1851d74001adSXin LI static void arcmsr_hbb_message_isr(struct AdapterControlBlock *acb) {
1852d74001adSXin LI 	u_int32_t outbound_message;
1853b23a1998SXin LI 	struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
1854d74001adSXin LI 
1855d74001adSXin LI 	/* clear interrupts */
1856b23a1998SXin LI 	WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell, ARCMSR_MESSAGE_INT_CLEAR_PATTERN);
1857d74001adSXin LI 	outbound_message = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[0]);
1858d74001adSXin LI 	if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG)
1859d74001adSXin LI 		arcmsr_dr_handle( acb );
1860d74001adSXin LI }
1861d74001adSXin LI /*
1862d74001adSXin LI **************************************************************************
1863d74001adSXin LI **************************************************************************
1864d74001adSXin LI */
1865d74001adSXin LI static void arcmsr_hbc_message_isr(struct AdapterControlBlock *acb) {
1866d74001adSXin LI 	u_int32_t outbound_message;
1867d74001adSXin LI 
1868d74001adSXin LI 	CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR);
1869d74001adSXin LI 	outbound_message = CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[0]);
1870d74001adSXin LI 	if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG)
1871d74001adSXin LI 		arcmsr_dr_handle( acb );
1872d74001adSXin LI }
187344f05562SScott Long /*
187444f05562SScott Long **************************************************************************
187544f05562SScott Long **************************************************************************
187644f05562SScott Long */
18777a7bc959SXin LI static void arcmsr_hbd_message_isr(struct AdapterControlBlock *acb) {
18787a7bc959SXin LI 	u_int32_t outbound_message;
18797a7bc959SXin LI 
18807a7bc959SXin LI 	CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE_CLEAR);
18817a7bc959SXin LI 	outbound_message = CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[0]);
18827a7bc959SXin LI 	if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG)
18837a7bc959SXin LI 		arcmsr_dr_handle( acb );
18847a7bc959SXin LI }
18857a7bc959SXin LI /*
18867a7bc959SXin LI **************************************************************************
18877a7bc959SXin LI **************************************************************************
18887a7bc959SXin LI */
1889a1103e04SXin LI static void arcmsr_hbe_message_isr(struct AdapterControlBlock *acb) {
1890a1103e04SXin LI 	u_int32_t outbound_message;
1891a1103e04SXin LI 
1892a1103e04SXin LI 	CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_status, 0);
18935842073aSXin LI 	if (acb->adapter_type == ACB_ADAPTER_TYPE_E)
1894a1103e04SXin LI 		outbound_message = CHIP_REG_READ32(HBE_MessageUnit, 0, msgcode_rwbuffer[0]);
18955842073aSXin LI 	else
18965842073aSXin LI 		outbound_message = acb->msgcode_rwbuffer[0];
1897a1103e04SXin LI 	if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG)
1898a1103e04SXin LI 		arcmsr_dr_handle( acb );
1899a1103e04SXin LI }
1900a1103e04SXin LI /*
1901a1103e04SXin LI **************************************************************************
1902a1103e04SXin LI **************************************************************************
1903a1103e04SXin LI */
190444f05562SScott Long static void arcmsr_hba_doorbell_isr(struct AdapterControlBlock *acb)
190544f05562SScott Long {
1906224a78aeSXin LI 	u_int32_t doorbell_status;
190744f05562SScott Long 
190844f05562SScott Long 	/*
190944f05562SScott Long 	*******************************************************************
191044f05562SScott Long 	**  Maybe here we need to check wrqbuffer_lock is lock or not
191144f05562SScott Long 	**  DOORBELL: din! don!
191244f05562SScott Long 	**  check if there are any mail need to pack from firmware
191344f05562SScott Long 	*******************************************************************
191444f05562SScott Long 	*/
1915224a78aeSXin LI 	doorbell_status = CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_doorbell);
1916224a78aeSXin LI 	CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_doorbell, doorbell_status); /* clear doorbell interrupt */
1917224a78aeSXin LI 	if(doorbell_status & ARCMSR_OUTBOUND_IOP331_DATA_WRITE_OK) {
191844f05562SScott Long 		arcmsr_iop2drv_data_wrote_handle(acb);
1919ad6d6297SScott Long 	}
1920224a78aeSXin LI 	if(doorbell_status & ARCMSR_OUTBOUND_IOP331_DATA_READ_OK) {
192144f05562SScott Long 		arcmsr_iop2drv_data_read_handle(acb);
192244f05562SScott Long 	}
192344f05562SScott Long }
192444f05562SScott Long /*
192544f05562SScott Long **************************************************************************
192644f05562SScott Long **************************************************************************
192744f05562SScott Long */
1928d74001adSXin LI static void arcmsr_hbc_doorbell_isr(struct AdapterControlBlock *acb)
1929d74001adSXin LI {
1930224a78aeSXin LI 	u_int32_t doorbell_status;
1931d74001adSXin LI 
1932d74001adSXin LI 	/*
1933d74001adSXin LI 	*******************************************************************
1934d74001adSXin LI 	**  Maybe here we need to check wrqbuffer_lock is lock or not
1935d74001adSXin LI 	**  DOORBELL: din! don!
1936d74001adSXin LI 	**  check if there are any mail need to pack from firmware
1937d74001adSXin LI 	*******************************************************************
1938d74001adSXin LI 	*/
1939224a78aeSXin LI 	doorbell_status = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell);
1940224a78aeSXin LI 	CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, doorbell_status); /* clear doorbell interrupt */
1941224a78aeSXin LI 	if(doorbell_status & ARCMSR_HBCMU_IOP2DRV_DATA_WRITE_OK) {
1942d74001adSXin LI 		arcmsr_iop2drv_data_wrote_handle(acb);
1943d74001adSXin LI 	}
1944224a78aeSXin LI 	if(doorbell_status & ARCMSR_HBCMU_IOP2DRV_DATA_READ_OK) {
1945d74001adSXin LI 		arcmsr_iop2drv_data_read_handle(acb);
1946d74001adSXin LI 	}
1947224a78aeSXin LI 	if(doorbell_status & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) {
1948d74001adSXin LI 		arcmsr_hbc_message_isr(acb);    /* messenger of "driver to iop commands" */
1949d74001adSXin LI 	}
1950d74001adSXin LI }
1951d74001adSXin LI /*
1952d74001adSXin LI **************************************************************************
1953d74001adSXin LI **************************************************************************
1954d74001adSXin LI */
19557a7bc959SXin LI static void arcmsr_hbd_doorbell_isr(struct AdapterControlBlock *acb)
19567a7bc959SXin LI {
1957224a78aeSXin LI 	u_int32_t doorbell_status;
19587a7bc959SXin LI 
19597a7bc959SXin LI 	/*
19607a7bc959SXin LI 	*******************************************************************
19617a7bc959SXin LI 	**  Maybe here we need to check wrqbuffer_lock is lock or not
19627a7bc959SXin LI 	**  DOORBELL: din! don!
19637a7bc959SXin LI 	**  check if there are any mail need to pack from firmware
19647a7bc959SXin LI 	*******************************************************************
19657a7bc959SXin LI 	*/
1966224a78aeSXin LI 	doorbell_status = CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBDMU_F0_DOORBELL_CAUSE;
1967224a78aeSXin LI 	if(doorbell_status)
1968224a78aeSXin LI 		CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, doorbell_status); /* clear doorbell interrupt */
1969224a78aeSXin LI 	while( doorbell_status & ARCMSR_HBDMU_F0_DOORBELL_CAUSE ) {
1970224a78aeSXin LI 		if(doorbell_status & ARCMSR_HBDMU_IOP2DRV_DATA_WRITE_OK) {
19717a7bc959SXin LI 			arcmsr_iop2drv_data_wrote_handle(acb);
19727a7bc959SXin LI 		}
1973224a78aeSXin LI 		if(doorbell_status & ARCMSR_HBDMU_IOP2DRV_DATA_READ_OK) {
19747a7bc959SXin LI 			arcmsr_iop2drv_data_read_handle(acb);
19757a7bc959SXin LI 		}
1976224a78aeSXin LI 		if(doorbell_status & ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE) {
19777a7bc959SXin LI 			arcmsr_hbd_message_isr(acb);    /* messenger of "driver to iop commands" */
19787a7bc959SXin LI 		}
1979224a78aeSXin LI 		doorbell_status = CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBDMU_F0_DOORBELL_CAUSE;
1980224a78aeSXin LI 		if(doorbell_status)
1981224a78aeSXin LI 			CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, doorbell_status); /* clear doorbell interrupt */
19827a7bc959SXin LI 	}
19837a7bc959SXin LI }
19847a7bc959SXin LI /*
19857a7bc959SXin LI **************************************************************************
19867a7bc959SXin LI **************************************************************************
19877a7bc959SXin LI */
1988a1103e04SXin LI static void arcmsr_hbe_doorbell_isr(struct AdapterControlBlock *acb)
1989a1103e04SXin LI {
1990a1103e04SXin LI 	u_int32_t doorbell_status, in_doorbell;
1991a1103e04SXin LI 
1992a1103e04SXin LI 	/*
1993a1103e04SXin LI 	*******************************************************************
1994a1103e04SXin LI 	**  Maybe here we need to check wrqbuffer_lock is lock or not
1995a1103e04SXin LI 	**  DOORBELL: din! don!
1996a1103e04SXin LI 	**  check if there are any mail need to pack from firmware
1997a1103e04SXin LI 	*******************************************************************
1998a1103e04SXin LI 	*/
1999a1103e04SXin LI 	in_doorbell = CHIP_REG_READ32(HBE_MessageUnit, 0, iobound_doorbell);
2000a1103e04SXin LI 	CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_status, 0); /* clear doorbell interrupt */
2001a1103e04SXin LI 	doorbell_status = in_doorbell ^ acb->in_doorbell;
2002a1103e04SXin LI 	if(doorbell_status & ARCMSR_HBEMU_IOP2DRV_DATA_WRITE_OK) {
2003a1103e04SXin LI 		arcmsr_iop2drv_data_wrote_handle(acb);
2004a1103e04SXin LI 	}
2005a1103e04SXin LI 	if(doorbell_status & ARCMSR_HBEMU_IOP2DRV_DATA_READ_OK) {
2006a1103e04SXin LI 		arcmsr_iop2drv_data_read_handle(acb);
2007a1103e04SXin LI 	}
2008a1103e04SXin LI 	if(doorbell_status & ARCMSR_HBEMU_IOP2DRV_MESSAGE_CMD_DONE) {
2009a1103e04SXin LI 		arcmsr_hbe_message_isr(acb);    /* messenger of "driver to iop commands" */
2010a1103e04SXin LI 	}
2011a1103e04SXin LI 	acb->in_doorbell = in_doorbell;
2012a1103e04SXin LI }
2013a1103e04SXin LI /*
2014a1103e04SXin LI **************************************************************************
2015a1103e04SXin LI **************************************************************************
2016a1103e04SXin LI */
20176964b77eS黃清隆 static void arcmsr_hbf_doorbell_isr(struct AdapterControlBlock *acb)
20186964b77eS黃清隆 {
20196964b77eS黃清隆 	u_int32_t doorbell_status, in_doorbell;
20206964b77eS黃清隆 
20216964b77eS黃清隆 	/*
20226964b77eS黃清隆 	*******************************************************************
20236964b77eS黃清隆 	**  Maybe here we need to check wrqbuffer_lock is lock or not
20246964b77eS黃清隆 	**  DOORBELL: din! don!
20256964b77eS黃清隆 	**  check if there are any mail need to pack from firmware
20266964b77eS黃清隆 	*******************************************************************
20276964b77eS黃清隆 	*/
20286964b77eS黃清隆 	while(1) {
20296964b77eS黃清隆 		in_doorbell = CHIP_REG_READ32(HBE_MessageUnit, 0, iobound_doorbell);
20306964b77eS黃清隆 		if ((in_doorbell != 0) && (in_doorbell != 0xFFFFFFFF))
20316964b77eS黃清隆 			break;
20326964b77eS黃清隆 	}
20336964b77eS黃清隆 	CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_status, 0); /* clear doorbell interrupt */
20346964b77eS黃清隆 	doorbell_status = in_doorbell ^ acb->in_doorbell;
20356964b77eS黃清隆 	if(doorbell_status & ARCMSR_HBEMU_IOP2DRV_DATA_WRITE_OK) {
20366964b77eS黃清隆 		arcmsr_iop2drv_data_wrote_handle(acb);
20376964b77eS黃清隆 	}
20386964b77eS黃清隆 	if(doorbell_status & ARCMSR_HBEMU_IOP2DRV_DATA_READ_OK) {
20396964b77eS黃清隆 		arcmsr_iop2drv_data_read_handle(acb);
20406964b77eS黃清隆 	}
20416964b77eS黃清隆 	if(doorbell_status & ARCMSR_HBEMU_IOP2DRV_MESSAGE_CMD_DONE) {
20426964b77eS黃清隆 		arcmsr_hbe_message_isr(acb);    /* messenger of "driver to iop commands" */
20436964b77eS黃清隆 	}
20446964b77eS黃清隆 	acb->in_doorbell = in_doorbell;
20456964b77eS黃清隆 }
20466964b77eS黃清隆 /*
20476964b77eS黃清隆 **************************************************************************
20486964b77eS黃清隆 **************************************************************************
20496964b77eS黃清隆 */
205044f05562SScott Long static void arcmsr_hba_postqueue_isr(struct AdapterControlBlock *acb)
205144f05562SScott Long {
205244f05562SScott Long 	u_int32_t flag_srb;
2053d74001adSXin LI 	u_int16_t error;
205444f05562SScott Long 
2055f1c579b1SScott Long 	/*
2056f1c579b1SScott Long 	*****************************************************************************
2057f1c579b1SScott Long 	**               areca cdb command done
2058f1c579b1SScott Long 	*****************************************************************************
2059f1c579b1SScott Long 	*/
206044f05562SScott Long 	bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap,
206144f05562SScott Long 		BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
206244f05562SScott Long 	while((flag_srb = CHIP_REG_READ32(HBA_MessageUnit,
206344f05562SScott Long 		0, outbound_queueport)) != 0xFFFFFFFF) {
2064f1c579b1SScott Long 		/* check if command done with no error*/
2065d74001adSXin LI 		error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0) ? TRUE : FALSE;
2066d74001adSXin LI 		arcmsr_drain_donequeue(acb, flag_srb, error);
206744f05562SScott Long 	}	/*drain reply FIFO*/
2068f1c579b1SScott Long }
206944f05562SScott Long /*
207044f05562SScott Long **************************************************************************
207144f05562SScott Long **************************************************************************
207244f05562SScott Long */
207344f05562SScott Long static void arcmsr_hbb_postqueue_isr(struct AdapterControlBlock *acb)
207444f05562SScott Long {
207544f05562SScott Long 	struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
207644f05562SScott Long 	u_int32_t flag_srb;
207744f05562SScott Long 	int index;
2078d74001adSXin LI 	u_int16_t error;
207944f05562SScott Long 
208044f05562SScott Long 	/*
208144f05562SScott Long 	*****************************************************************************
208244f05562SScott Long 	**               areca cdb command done
208344f05562SScott Long 	*****************************************************************************
208444f05562SScott Long 	*/
208544f05562SScott Long 	bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap,
208644f05562SScott Long 		BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
208744f05562SScott Long 	index = phbbmu->doneq_index;
208844f05562SScott Long 	while((flag_srb = phbbmu->done_qbuffer[index]) != 0) {
208944f05562SScott Long 		phbbmu->done_qbuffer[index] = 0;
209044f05562SScott Long 		index++;
209144f05562SScott Long 		index %= ARCMSR_MAX_HBB_POSTQUEUE;     /*if last index number set it to 0 */
209244f05562SScott Long 		phbbmu->doneq_index = index;
209344f05562SScott Long 		/* check if command done with no error*/
2094d74001adSXin LI 		error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE;
2095d74001adSXin LI 		arcmsr_drain_donequeue(acb, flag_srb, error);
2096d74001adSXin LI 	}	/*drain reply FIFO*/
2097d74001adSXin LI }
2098d74001adSXin LI /*
2099d74001adSXin LI **************************************************************************
2100d74001adSXin LI **************************************************************************
2101d74001adSXin LI */
2102d74001adSXin LI static void arcmsr_hbc_postqueue_isr(struct AdapterControlBlock *acb)
2103d74001adSXin LI {
2104d74001adSXin LI 	u_int32_t flag_srb,throttling = 0;
2105d74001adSXin LI 	u_int16_t error;
2106d74001adSXin LI 
2107d74001adSXin LI 	/*
2108d74001adSXin LI 	*****************************************************************************
2109d74001adSXin LI 	**               areca cdb command done
2110d74001adSXin LI 	*****************************************************************************
2111d74001adSXin LI 	*/
2112d74001adSXin LI 	bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
2113224a78aeSXin LI 	do {
2114d74001adSXin LI 		flag_srb = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_queueport_low);
2115b23a1998SXin LI 		if (flag_srb == 0xFFFFFFFF)
2116b23a1998SXin LI 			break;
2117d74001adSXin LI 		/* check if command done with no error*/
2118d74001adSXin LI 		error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1)?TRUE:FALSE;
2119d74001adSXin LI 		arcmsr_drain_donequeue(acb, flag_srb, error);
2120abfdbca9SXin LI 		throttling++;
2121d74001adSXin LI 		if(throttling == ARCMSR_HBC_ISR_THROTTLING_LEVEL) {
2122d74001adSXin LI 			CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_POSTQUEUE_THROTTLING);
2123abfdbca9SXin LI 			throttling = 0;
2124d74001adSXin LI 		}
2125224a78aeSXin LI 	} while(CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR);
2126f1c579b1SScott Long }
212744f05562SScott Long /*
212844f05562SScott Long **********************************************************************
21297a7bc959SXin LI **
21307a7bc959SXin LI **********************************************************************
21317a7bc959SXin LI */
21327a7bc959SXin LI static uint16_t arcmsr_get_doneq_index(struct HBD_MessageUnit0 *phbdmu)
21337a7bc959SXin LI {
21347a7bc959SXin LI 	uint16_t doneq_index, index_stripped;
21357a7bc959SXin LI 
21367a7bc959SXin LI 	doneq_index = phbdmu->doneq_index;
21377a7bc959SXin LI 	if (doneq_index & 0x4000) {
21387a7bc959SXin LI 		index_stripped = doneq_index & 0xFF;
21397a7bc959SXin LI 		index_stripped += 1;
21407a7bc959SXin LI 		index_stripped %= ARCMSR_MAX_HBD_POSTQUEUE;
21417a7bc959SXin LI 		phbdmu->doneq_index = index_stripped ?
21427a7bc959SXin LI 		    (index_stripped | 0x4000) : index_stripped;
21437a7bc959SXin LI 	} else {
21447a7bc959SXin LI 		index_stripped = doneq_index;
21457a7bc959SXin LI 		index_stripped += 1;
21467a7bc959SXin LI 		index_stripped %= ARCMSR_MAX_HBD_POSTQUEUE;
21477a7bc959SXin LI 		phbdmu->doneq_index = index_stripped ?
21487a7bc959SXin LI 		    index_stripped : (index_stripped | 0x4000);
21497a7bc959SXin LI 	}
21507a7bc959SXin LI 	return (phbdmu->doneq_index);
21517a7bc959SXin LI }
21527a7bc959SXin LI /*
21537a7bc959SXin LI **************************************************************************
21547a7bc959SXin LI **************************************************************************
21557a7bc959SXin LI */
21567a7bc959SXin LI static void arcmsr_hbd_postqueue_isr(struct AdapterControlBlock *acb)
21577a7bc959SXin LI {
21587a7bc959SXin LI 	struct HBD_MessageUnit0 *phbdmu = (struct HBD_MessageUnit0 *)acb->pmu;
21597a7bc959SXin LI 	u_int32_t outbound_write_pointer;
21607a7bc959SXin LI 	u_int32_t addressLow;
21617a7bc959SXin LI 	uint16_t doneq_index;
21627a7bc959SXin LI 	u_int16_t error;
21637a7bc959SXin LI 	/*
21647a7bc959SXin LI 	*****************************************************************************
21657a7bc959SXin LI 	**               areca cdb command done
21667a7bc959SXin LI 	*****************************************************************************
21677a7bc959SXin LI 	*/
21687a7bc959SXin LI 	if((CHIP_REG_READ32(HBD_MessageUnit, 0, outboundlist_interrupt_cause) &
21697a7bc959SXin LI 		ARCMSR_HBDMU_OUTBOUND_LIST_INTERRUPT) == 0)
21707a7bc959SXin LI 		return;
21717a7bc959SXin LI 	bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap,
21727a7bc959SXin LI 		BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
21737a7bc959SXin LI 	outbound_write_pointer = phbdmu->done_qbuffer[0].addressLow;
21747a7bc959SXin LI 	doneq_index = phbdmu->doneq_index;
21757a7bc959SXin LI 	while ((doneq_index & 0xFF) != (outbound_write_pointer & 0xFF)) {
21767a7bc959SXin LI 		doneq_index = arcmsr_get_doneq_index(phbdmu);
21777a7bc959SXin LI 		addressLow = phbdmu->done_qbuffer[(doneq_index & 0xFF)+1].addressLow;
21787a7bc959SXin LI 		error = (addressLow & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE;
21797a7bc959SXin LI 		arcmsr_drain_donequeue(acb, addressLow, error); /*Check if command done with no error */
21807a7bc959SXin LI 		CHIP_REG_WRITE32(HBD_MessageUnit, 0, outboundlist_read_pointer, doneq_index);
21817a7bc959SXin LI 		outbound_write_pointer = phbdmu->done_qbuffer[0].addressLow;
21827a7bc959SXin LI 	}
21837a7bc959SXin LI 	CHIP_REG_WRITE32(HBD_MessageUnit, 0, outboundlist_interrupt_cause, ARCMSR_HBDMU_OUTBOUND_LIST_INTERRUPT_CLEAR);
21847a7bc959SXin LI 	CHIP_REG_READ32(HBD_MessageUnit, 0, outboundlist_interrupt_cause); /*Dummy ioread32 to force pci flush */
21857a7bc959SXin LI }
21867a7bc959SXin LI /*
2187a1103e04SXin LI **************************************************************************
2188a1103e04SXin LI **************************************************************************
2189a1103e04SXin LI */
2190a1103e04SXin LI static void arcmsr_hbe_postqueue_isr(struct AdapterControlBlock *acb)
2191a1103e04SXin LI {
2192a1103e04SXin LI 	u_int16_t error;
2193a1103e04SXin LI 	uint32_t doneq_index;
2194a1103e04SXin LI 	uint16_t cmdSMID;
2195a1103e04SXin LI 
2196a1103e04SXin LI 	/*
2197a1103e04SXin LI 	*****************************************************************************
2198a1103e04SXin LI 	**               areca cdb command done
2199a1103e04SXin LI 	*****************************************************************************
2200a1103e04SXin LI 	*/
2201a1103e04SXin LI 	bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
2202a1103e04SXin LI 	doneq_index = acb->doneq_index;
2203a1103e04SXin LI 	while ((CHIP_REG_READ32(HBE_MessageUnit, 0, reply_post_producer_index) & 0xFFFF) != doneq_index) {
2204a1103e04SXin LI 		cmdSMID = acb->pCompletionQ[doneq_index].cmdSMID;
2205a1103e04SXin LI 		error = (acb->pCompletionQ[doneq_index].cmdFlag & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE;
2206a1103e04SXin LI 		arcmsr_drain_donequeue(acb, (u_int32_t)cmdSMID, error);
2207a1103e04SXin LI 		doneq_index++;
2208a1103e04SXin LI 		if (doneq_index >= acb->completionQ_entry)
2209a1103e04SXin LI 			doneq_index = 0;
2210a1103e04SXin LI 	}
2211a1103e04SXin LI 	acb->doneq_index = doneq_index;
2212a1103e04SXin LI 	CHIP_REG_WRITE32(HBE_MessageUnit, 0, reply_post_consumer_index, doneq_index);
2213a1103e04SXin LI }
2214fa42a0bfSXin LI 
2215fa42a0bfSXin LI static void arcmsr_hbf_postqueue_isr(struct AdapterControlBlock *acb)
2216fa42a0bfSXin LI {
2217fa42a0bfSXin LI 	uint16_t error;
2218fa42a0bfSXin LI 	uint32_t doneq_index;
2219fa42a0bfSXin LI 	uint16_t cmdSMID;
2220fa42a0bfSXin LI 
2221fa42a0bfSXin LI 	/*
2222fa42a0bfSXin LI 	*****************************************************************************
2223fa42a0bfSXin LI 	**               areca cdb command done
2224fa42a0bfSXin LI 	*****************************************************************************
2225fa42a0bfSXin LI 	*/
2226fa42a0bfSXin LI 	bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
2227fa42a0bfSXin LI 	doneq_index = acb->doneq_index;
2228fa42a0bfSXin LI 	while (1) {
2229fa42a0bfSXin LI 		cmdSMID = acb->pCompletionQ[doneq_index].cmdSMID;
2230fa42a0bfSXin LI 		if (cmdSMID == 0xffff)
2231fa42a0bfSXin LI 			break;
2232fa42a0bfSXin LI 		error = (acb->pCompletionQ[doneq_index].cmdFlag & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE;
2233fa42a0bfSXin LI 		arcmsr_drain_donequeue(acb, (u_int32_t)cmdSMID, error);
2234fa42a0bfSXin LI 		acb->pCompletionQ[doneq_index].cmdSMID = 0xffff;
2235fa42a0bfSXin LI 		doneq_index++;
2236fa42a0bfSXin LI 		if (doneq_index >= acb->completionQ_entry)
2237fa42a0bfSXin LI 			doneq_index = 0;
2238fa42a0bfSXin LI 	}
2239fa42a0bfSXin LI 	acb->doneq_index = doneq_index;
2240fa42a0bfSXin LI 	CHIP_REG_WRITE32(HBF_MessageUnit, 0, reply_post_consumer_index, doneq_index);
2241fa42a0bfSXin LI }
2242fa42a0bfSXin LI 
2243a1103e04SXin LI /*
22447a7bc959SXin LI **********************************************************************
224544f05562SScott Long **********************************************************************
224644f05562SScott Long */
224744f05562SScott Long static void arcmsr_handle_hba_isr( struct AdapterControlBlock *acb)
224844f05562SScott Long {
2249dac36688SXin LI 	u_int32_t outbound_intStatus;
225044f05562SScott Long 	/*
225144f05562SScott Long 	*********************************************
225244f05562SScott Long 	**   check outbound intstatus
225344f05562SScott Long 	*********************************************
225444f05562SScott Long 	*/
2255dac36688SXin LI 	outbound_intStatus = CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & acb->outbound_int_enable;
2256dac36688SXin LI 	if(!outbound_intStatus) {
225744f05562SScott Long 		/*it must be share irq*/
225844f05562SScott Long 		return;
2259f1c579b1SScott Long 	}
2260dac36688SXin LI 	CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, outbound_intStatus); /*clear interrupt*/
226144f05562SScott Long 	/* MU doorbell interrupts*/
2262dac36688SXin LI 	if(outbound_intStatus & ARCMSR_MU_OUTBOUND_DOORBELL_INT) {
226344f05562SScott Long 		arcmsr_hba_doorbell_isr(acb);
2264f1c579b1SScott Long 	}
226544f05562SScott Long 	/* MU post queue interrupts*/
2266dac36688SXin LI 	if(outbound_intStatus & ARCMSR_MU_OUTBOUND_POSTQUEUE_INT) {
226744f05562SScott Long 		arcmsr_hba_postqueue_isr(acb);
226844f05562SScott Long 	}
2269dac36688SXin LI 	if(outbound_intStatus & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) {
2270d74001adSXin LI 		arcmsr_hba_message_isr(acb);
2271d74001adSXin LI 	}
227244f05562SScott Long }
227344f05562SScott Long /*
227444f05562SScott Long **********************************************************************
227544f05562SScott Long **********************************************************************
227644f05562SScott Long */
227744f05562SScott Long static void arcmsr_handle_hbb_isr( struct AdapterControlBlock *acb)
227844f05562SScott Long {
227944f05562SScott Long 	u_int32_t outbound_doorbell;
2280b23a1998SXin LI 	struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
228144f05562SScott Long 	/*
228244f05562SScott Long 	*********************************************
228344f05562SScott Long 	**   check outbound intstatus
228444f05562SScott Long 	*********************************************
228544f05562SScott Long 	*/
2286b23a1998SXin LI 	outbound_doorbell = READ_CHIP_REG32(0, phbbmu->iop2drv_doorbell) & acb->outbound_int_enable;
228744f05562SScott Long 	if(!outbound_doorbell) {
228844f05562SScott Long 		/*it must be share irq*/
228944f05562SScott Long 		return;
229044f05562SScott Long 	}
2291b23a1998SXin LI 	WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell, ~outbound_doorbell); /* clear doorbell interrupt */
2292b23a1998SXin LI 	READ_CHIP_REG32(0, phbbmu->iop2drv_doorbell);
2293b23a1998SXin LI 	WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT);
229444f05562SScott Long 	/* MU ioctl transfer doorbell interrupts*/
229544f05562SScott Long 	if(outbound_doorbell & ARCMSR_IOP2DRV_DATA_WRITE_OK) {
229644f05562SScott Long 		arcmsr_iop2drv_data_wrote_handle(acb);
229744f05562SScott Long 	}
229844f05562SScott Long 	if(outbound_doorbell & ARCMSR_IOP2DRV_DATA_READ_OK) {
229944f05562SScott Long 		arcmsr_iop2drv_data_read_handle(acb);
230044f05562SScott Long 	}
230144f05562SScott Long 	/* MU post queue interrupts*/
230244f05562SScott Long 	if(outbound_doorbell & ARCMSR_IOP2DRV_CDB_DONE) {
230344f05562SScott Long 		arcmsr_hbb_postqueue_isr(acb);
230444f05562SScott Long 	}
2305d74001adSXin LI 	if(outbound_doorbell & ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) {
2306d74001adSXin LI 		arcmsr_hbb_message_isr(acb);
2307d74001adSXin LI 	}
2308d74001adSXin LI }
2309d74001adSXin LI /*
2310d74001adSXin LI **********************************************************************
2311d74001adSXin LI **********************************************************************
2312d74001adSXin LI */
2313d74001adSXin LI static void arcmsr_handle_hbc_isr( struct AdapterControlBlock *acb)
2314d74001adSXin LI {
2315d74001adSXin LI 	u_int32_t host_interrupt_status;
2316d74001adSXin LI 	/*
2317d74001adSXin LI 	*********************************************
2318d74001adSXin LI 	**   check outbound intstatus
2319d74001adSXin LI 	*********************************************
2320d74001adSXin LI 	*/
2321224a78aeSXin LI 	host_interrupt_status = CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) &
2322224a78aeSXin LI 		(ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR |
2323224a78aeSXin LI 		ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR);
2324d74001adSXin LI 	if(!host_interrupt_status) {
2325d74001adSXin LI 		/*it must be share irq*/
2326d74001adSXin LI 		return;
2327d74001adSXin LI 	}
2328224a78aeSXin LI 	do {
2329d74001adSXin LI 		/* MU doorbell interrupts*/
2330d74001adSXin LI 		if(host_interrupt_status & ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR) {
2331d74001adSXin LI 			arcmsr_hbc_doorbell_isr(acb);
2332d74001adSXin LI 		}
2333d74001adSXin LI 		/* MU post queue interrupts*/
2334d74001adSXin LI 		if(host_interrupt_status & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) {
2335d74001adSXin LI 			arcmsr_hbc_postqueue_isr(acb);
2336d74001adSXin LI 		}
2337224a78aeSXin LI 		host_interrupt_status = CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status);
2338224a78aeSXin LI 	} while (host_interrupt_status & (ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR | ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR));
233944f05562SScott Long }
234044f05562SScott Long /*
23417a7bc959SXin LI **********************************************************************
23427a7bc959SXin LI **********************************************************************
23437a7bc959SXin LI */
23447a7bc959SXin LI static void arcmsr_handle_hbd_isr( struct AdapterControlBlock *acb)
23457a7bc959SXin LI {
23467a7bc959SXin LI 	u_int32_t host_interrupt_status;
23477a7bc959SXin LI 	u_int32_t intmask_org;
23487a7bc959SXin LI 	/*
23497a7bc959SXin LI 	*********************************************
23507a7bc959SXin LI 	**   check outbound intstatus
23517a7bc959SXin LI 	*********************************************
23527a7bc959SXin LI 	*/
23537a7bc959SXin LI 	host_interrupt_status = CHIP_REG_READ32(HBD_MessageUnit, 0, host_int_status) & acb->outbound_int_enable;
23547a7bc959SXin LI 	if(!(host_interrupt_status & ARCMSR_HBDMU_OUTBOUND_INT)) {
23557a7bc959SXin LI 		/*it must be share irq*/
23567a7bc959SXin LI 		return;
23577a7bc959SXin LI 	}
23587a7bc959SXin LI 	/* disable outbound interrupt */
23597a7bc959SXin LI 	intmask_org = CHIP_REG_READ32(HBD_MessageUnit, 0, pcief0_int_enable)	; /* disable outbound message0 int */
23607a7bc959SXin LI 	CHIP_REG_WRITE32(HBD_MessageUnit, 0, pcief0_int_enable, ARCMSR_HBDMU_ALL_INT_DISABLE);
23617a7bc959SXin LI 	/* MU doorbell interrupts*/
23627a7bc959SXin LI 	if(host_interrupt_status & ARCMSR_HBDMU_OUTBOUND_DOORBELL_INT) {
23637a7bc959SXin LI 		arcmsr_hbd_doorbell_isr(acb);
23647a7bc959SXin LI 	}
23657a7bc959SXin LI 	/* MU post queue interrupts*/
23667a7bc959SXin LI 	if(host_interrupt_status & ARCMSR_HBDMU_OUTBOUND_POSTQUEUE_INT) {
23677a7bc959SXin LI 		arcmsr_hbd_postqueue_isr(acb);
23687a7bc959SXin LI 	}
23697a7bc959SXin LI 	/* enable all outbound interrupt */
23707a7bc959SXin LI 	CHIP_REG_WRITE32(HBD_MessageUnit, 0, pcief0_int_enable, intmask_org | ARCMSR_HBDMU_ALL_INT_ENABLE);
23717a7bc959SXin LI //	CHIP_REG_READ32(HBD_MessageUnit, 0, pcief0_int_enable);
23727a7bc959SXin LI }
23737a7bc959SXin LI /*
2374a1103e04SXin LI **********************************************************************
2375a1103e04SXin LI **********************************************************************
2376a1103e04SXin LI */
2377a1103e04SXin LI static void arcmsr_handle_hbe_isr( struct AdapterControlBlock *acb)
2378a1103e04SXin LI {
2379a1103e04SXin LI 	u_int32_t host_interrupt_status;
2380a1103e04SXin LI 	/*
2381a1103e04SXin LI 	*********************************************
2382a1103e04SXin LI 	**   check outbound intstatus
2383a1103e04SXin LI 	*********************************************
2384a1103e04SXin LI 	*/
2385a1103e04SXin LI 	host_interrupt_status = CHIP_REG_READ32(HBE_MessageUnit, 0, host_int_status) &
2386a1103e04SXin LI 		(ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR |
2387a1103e04SXin LI 		ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR);
2388a1103e04SXin LI 	if(!host_interrupt_status) {
2389a1103e04SXin LI 		/*it must be share irq*/
2390a1103e04SXin LI 		return;
2391a1103e04SXin LI 	}
2392a1103e04SXin LI 	do {
2393a1103e04SXin LI 		/* MU doorbell interrupts*/
2394a1103e04SXin LI 		if(host_interrupt_status & ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR) {
2395a1103e04SXin LI 			arcmsr_hbe_doorbell_isr(acb);
2396a1103e04SXin LI 		}
2397a1103e04SXin LI 		/* MU post queue interrupts*/
2398a1103e04SXin LI 		if(host_interrupt_status & ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR) {
2399a1103e04SXin LI 			arcmsr_hbe_postqueue_isr(acb);
2400a1103e04SXin LI 		}
2401a1103e04SXin LI 		host_interrupt_status = CHIP_REG_READ32(HBE_MessageUnit, 0, host_int_status);
2402a1103e04SXin LI 	} while (host_interrupt_status & (ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR | ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR));
2403a1103e04SXin LI }
2404fa42a0bfSXin LI 
2405fa42a0bfSXin LI static void arcmsr_handle_hbf_isr( struct AdapterControlBlock *acb)
2406fa42a0bfSXin LI {
2407fa42a0bfSXin LI 	u_int32_t host_interrupt_status;
2408fa42a0bfSXin LI 	/*
2409fa42a0bfSXin LI 	*********************************************
2410fa42a0bfSXin LI 	**   check outbound intstatus
2411fa42a0bfSXin LI 	*********************************************
2412fa42a0bfSXin LI 	*/
2413fa42a0bfSXin LI 	host_interrupt_status = CHIP_REG_READ32(HBF_MessageUnit, 0, host_int_status) &
2414fa42a0bfSXin LI 		(ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR |
2415fa42a0bfSXin LI 		ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR);
2416fa42a0bfSXin LI 	if(!host_interrupt_status) {
2417fa42a0bfSXin LI 		/*it must be share irq*/
2418fa42a0bfSXin LI 		return;
2419fa42a0bfSXin LI 	}
2420fa42a0bfSXin LI 	do {
2421fa42a0bfSXin LI 		/* MU doorbell interrupts*/
2422fa42a0bfSXin LI 		if(host_interrupt_status & ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR) {
24236964b77eS黃清隆 			arcmsr_hbf_doorbell_isr(acb);
2424fa42a0bfSXin LI 		}
2425fa42a0bfSXin LI 		/* MU post queue interrupts*/
2426fa42a0bfSXin LI 		if(host_interrupt_status & ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR) {
2427fa42a0bfSXin LI 			arcmsr_hbf_postqueue_isr(acb);
2428fa42a0bfSXin LI 		}
2429fa42a0bfSXin LI 		host_interrupt_status = CHIP_REG_READ32(HBF_MessageUnit, 0, host_int_status);
2430fa42a0bfSXin LI 	} while (host_interrupt_status & (ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR | ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR));
2431fa42a0bfSXin LI }
2432a1103e04SXin LI /*
243344f05562SScott Long ******************************************************************************
243444f05562SScott Long ******************************************************************************
243544f05562SScott Long */
243644f05562SScott Long static void arcmsr_interrupt(struct AdapterControlBlock *acb)
243744f05562SScott Long {
243844f05562SScott Long 	switch (acb->adapter_type) {
243944f05562SScott Long 	case ACB_ADAPTER_TYPE_A:
244044f05562SScott Long 		arcmsr_handle_hba_isr(acb);
2441f1c579b1SScott Long 		break;
244244f05562SScott Long 	case ACB_ADAPTER_TYPE_B:
244344f05562SScott Long 		arcmsr_handle_hbb_isr(acb);
2444f1c579b1SScott Long 		break;
2445d74001adSXin LI 	case ACB_ADAPTER_TYPE_C:
2446d74001adSXin LI 		arcmsr_handle_hbc_isr(acb);
2447d74001adSXin LI 		break;
24487a7bc959SXin LI 	case ACB_ADAPTER_TYPE_D:
24497a7bc959SXin LI 		arcmsr_handle_hbd_isr(acb);
24507a7bc959SXin LI 		break;
2451a1103e04SXin LI 	case ACB_ADAPTER_TYPE_E:
2452a1103e04SXin LI 		arcmsr_handle_hbe_isr(acb);
2453a1103e04SXin LI 		break;
2454fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_F:
2455fa42a0bfSXin LI 		arcmsr_handle_hbf_isr(acb);
2456fa42a0bfSXin LI 		break;
2457f1c579b1SScott Long 	default:
245844f05562SScott Long 		printf("arcmsr%d: interrupt service,"
245910d66948SKevin Lo 		" unknown adapter type =%d\n", acb->pci_unit, acb->adapter_type);
2460f1c579b1SScott Long 		break;
2461f1c579b1SScott Long 	}
2462f1c579b1SScott Long }
2463f1c579b1SScott Long /*
2464d74001adSXin LI **********************************************************************
2465d74001adSXin LI **********************************************************************
2466d74001adSXin LI */
2467d74001adSXin LI static void arcmsr_intr_handler(void *arg)
2468d74001adSXin LI {
2469d74001adSXin LI 	struct AdapterControlBlock *acb = (struct AdapterControlBlock *)arg;
2470d74001adSXin LI 
24717a7bc959SXin LI 	ARCMSR_LOCK_ACQUIRE(&acb->isr_lock);
2472d74001adSXin LI 	arcmsr_interrupt(acb);
24737a7bc959SXin LI 	ARCMSR_LOCK_RELEASE(&acb->isr_lock);
2474d74001adSXin LI }
2475d74001adSXin LI /*
2476d74001adSXin LI ******************************************************************************
2477d74001adSXin LI ******************************************************************************
2478d74001adSXin LI */
2479d74001adSXin LI static void	arcmsr_polling_devmap(void *arg)
2480d74001adSXin LI {
2481d74001adSXin LI 	struct AdapterControlBlock *acb = (struct AdapterControlBlock *)arg;
2482d74001adSXin LI 	switch (acb->adapter_type) {
2483d74001adSXin LI 	case ACB_ADAPTER_TYPE_A:
2484dac36688SXin LI 		CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG);
2485d74001adSXin LI 		break;
2486d74001adSXin LI 
2487b23a1998SXin LI 	case ACB_ADAPTER_TYPE_B: {
2488b23a1998SXin LI 			struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
2489b23a1998SXin LI 			WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_GET_CONFIG);
2490b23a1998SXin LI 		}
2491d74001adSXin LI 		break;
2492d74001adSXin LI 
2493d74001adSXin LI 	case ACB_ADAPTER_TYPE_C:
2494d74001adSXin LI 		CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG);
2495d74001adSXin LI 		CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE);
2496d74001adSXin LI 		break;
24977a7bc959SXin LI 
24987a7bc959SXin LI 	case ACB_ADAPTER_TYPE_D:
24997a7bc959SXin LI 		CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG);
25007a7bc959SXin LI 		break;
2501a1103e04SXin LI 
2502a1103e04SXin LI 	case ACB_ADAPTER_TYPE_E:
2503a1103e04SXin LI 		CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG);
2504a1103e04SXin LI 		acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
2505a1103e04SXin LI 		CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
2506a1103e04SXin LI 		break;
2507d74001adSXin LI 
2508fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_F: {
2509fa42a0bfSXin LI 		u_int32_t outMsg1 = CHIP_REG_READ32(HBF_MessageUnit, 0, outbound_msgaddr1);
2510fa42a0bfSXin LI 		if (!(outMsg1 & ARCMSR_HBFMU_MESSAGE_FIRMWARE_OK) ||
2511fa42a0bfSXin LI 			(outMsg1 & ARCMSR_HBFMU_MESSAGE_NO_VOLUME_CHANGE))
2512fa42a0bfSXin LI 			goto nxt6s;
2513fa42a0bfSXin LI 		CHIP_REG_WRITE32(HBF_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG);
2514fa42a0bfSXin LI 		acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
2515fa42a0bfSXin LI 		CHIP_REG_WRITE32(HBF_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
2516fa42a0bfSXin LI 		break;
2517fa42a0bfSXin LI 		}
2518fa42a0bfSXin LI 	}
2519fa42a0bfSXin LI nxt6s:
2520d74001adSXin LI 	if((acb->acb_flags & ACB_F_SCSISTOPADAPTER) == 0)
2521d74001adSXin LI 	{
2522d74001adSXin LI 		callout_reset(&acb->devmap_callout, 5 * hz, arcmsr_polling_devmap, acb);	/* polling per 5 seconds */
2523d74001adSXin LI 	}
2524d74001adSXin LI }
2525d74001adSXin LI 
2526d74001adSXin LI /*
2527ad6d6297SScott Long *******************************************************************************
2528ad6d6297SScott Long **
2529ad6d6297SScott Long *******************************************************************************
2530ad6d6297SScott Long */
2531ad6d6297SScott Long static void arcmsr_iop_parking(struct AdapterControlBlock *acb)
2532ad6d6297SScott Long {
2533d74001adSXin LI 	u_int32_t intmask_org;
2534d74001adSXin LI 
2535ad6d6297SScott Long 	if(acb != NULL) {
2536ad6d6297SScott Long 		/* stop adapter background rebuild */
2537ad6d6297SScott Long 		if(acb->acb_flags & ACB_F_MSG_START_BGRB) {
2538d74001adSXin LI 			intmask_org = arcmsr_disable_allintr(acb);
2539ad6d6297SScott Long 			arcmsr_stop_adapter_bgrb(acb);
2540ad6d6297SScott Long 			arcmsr_flush_adapter_cache(acb);
2541d74001adSXin LI 			arcmsr_enable_allintr(acb, intmask_org);
2542ad6d6297SScott Long 		}
2543ad6d6297SScott Long 	}
2544ad6d6297SScott Long }
2545ad6d6297SScott Long /*
2546f1c579b1SScott Long ***********************************************************************
2547f1c579b1SScott Long **
2548f1c579b1SScott Long ************************************************************************
2549f1c579b1SScott Long */
2550fc5ef1caSXin LI static u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t ioctl_cmd, caddr_t arg)
2551f1c579b1SScott Long {
2552ad6d6297SScott Long 	struct CMD_MESSAGE_FIELD *pcmdmessagefld;
2553ad6d6297SScott Long 	u_int32_t retvalue = EINVAL;
2554f1c579b1SScott Long 
2555ad6d6297SScott Long 	pcmdmessagefld = (struct CMD_MESSAGE_FIELD *) arg;
2556ad6d6297SScott Long 	if(memcmp(pcmdmessagefld->cmdmessage.Signature, "ARCMSR", 6)!=0) {
2557ad6d6297SScott Long 		return retvalue;
2558f1c579b1SScott Long 	}
2559ad6d6297SScott Long 	ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
2560ad6d6297SScott Long 	switch(ioctl_cmd) {
2561ad6d6297SScott Long 	case ARCMSR_MESSAGE_READ_RQBUFFER: {
2562ad6d6297SScott Long 			u_int8_t *pQbuffer;
2563ad6d6297SScott Long 			u_int8_t *ptmpQbuffer = pcmdmessagefld->messagedatabuffer;
2564ad6d6297SScott Long 			u_int32_t allxfer_len=0;
2565f1c579b1SScott Long 
256644f05562SScott Long 			while((acb->rqbuf_firstindex != acb->rqbuf_lastindex)
256744f05562SScott Long 				&& (allxfer_len < 1031)) {
2568f1c579b1SScott Long 				/*copy READ QBUFFER to srb*/
2569ad6d6297SScott Long 				pQbuffer = &acb->rqbuffer[acb->rqbuf_firstindex];
25707a7bc959SXin LI 				*ptmpQbuffer = *pQbuffer;
2571ad6d6297SScott Long 				acb->rqbuf_firstindex++;
2572ad6d6297SScott Long 				acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER;
2573ad6d6297SScott Long 				/*if last index number set it to 0 */
2574f1c579b1SScott Long 				ptmpQbuffer++;
2575f1c579b1SScott Long 				allxfer_len++;
2576f1c579b1SScott Long 			}
2577ad6d6297SScott Long 			if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
257844f05562SScott Long 				struct QBUFFER *prbuffer;
2579f1c579b1SScott Long 
2580ad6d6297SScott Long 				acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
258144f05562SScott Long 				prbuffer = arcmsr_get_iop_rqbuffer(acb);
258235689395SXin LI 				if(arcmsr_Read_iop_rqbuffer_data(acb, prbuffer) == 0)
258335689395SXin LI 					acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW;
2584f1c579b1SScott Long 			}
2585ad6d6297SScott Long 			pcmdmessagefld->cmdmessage.Length = allxfer_len;
2586ad6d6297SScott Long 			pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
2587ad6d6297SScott Long 			retvalue = ARCMSR_MESSAGE_SUCCESS;
2588f1c579b1SScott Long 		}
2589f1c579b1SScott Long 		break;
2590ad6d6297SScott Long 	case ARCMSR_MESSAGE_WRITE_WQBUFFER: {
2591ad6d6297SScott Long 			u_int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex;
2592ad6d6297SScott Long 			u_int8_t *pQbuffer;
2593ad6d6297SScott Long 			u_int8_t *ptmpuserbuffer = pcmdmessagefld->messagedatabuffer;
2594f1c579b1SScott Long 
2595ad6d6297SScott Long 			user_len = pcmdmessagefld->cmdmessage.Length;
2596f1c579b1SScott Long 			/*check if data xfer length of this request will overflow my array qbuffer */
2597ad6d6297SScott Long 			wqbuf_lastindex = acb->wqbuf_lastindex;
2598ad6d6297SScott Long 			wqbuf_firstindex = acb->wqbuf_firstindex;
2599ad6d6297SScott Long 			if(wqbuf_lastindex != wqbuf_firstindex) {
26007a7bc959SXin LI 				arcmsr_Write_data_2iop_wqbuffer(acb);
2601ad6d6297SScott Long 				pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_ERROR;
2602ad6d6297SScott Long 			} else {
26037a7bc959SXin LI 				my_empty_len = (wqbuf_firstindex - wqbuf_lastindex - 1) &
26047a7bc959SXin LI 					(ARCMSR_MAX_QBUFFER - 1);
2605ad6d6297SScott Long 				if(my_empty_len >= user_len) {
2606ad6d6297SScott Long 					while(user_len > 0) {
2607f1c579b1SScott Long 						/*copy srb data to wqbuffer*/
2608ad6d6297SScott Long 						pQbuffer = &acb->wqbuffer[acb->wqbuf_lastindex];
26097a7bc959SXin LI 						*pQbuffer = *ptmpuserbuffer;
2610ad6d6297SScott Long 						acb->wqbuf_lastindex++;
2611ad6d6297SScott Long 						acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER;
2612ad6d6297SScott Long 						/*if last index number set it to 0 */
2613f1c579b1SScott Long 						ptmpuserbuffer++;
2614f1c579b1SScott Long 						user_len--;
2615f1c579b1SScott Long 					}
2616f1c579b1SScott Long 					/*post fist Qbuffer*/
2617ad6d6297SScott Long 					if(acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) {
2618ad6d6297SScott Long 						acb->acb_flags &= ~ACB_F_MESSAGE_WQBUFFER_CLEARED;
26197a7bc959SXin LI 						arcmsr_Write_data_2iop_wqbuffer(acb);
2620f1c579b1SScott Long 					}
2621ad6d6297SScott Long 					pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
2622ad6d6297SScott Long 				} else {
2623ad6d6297SScott Long 					pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_ERROR;
2624f1c579b1SScott Long 				}
2625f1c579b1SScott Long 			}
2626ad6d6297SScott Long 			retvalue = ARCMSR_MESSAGE_SUCCESS;
2627f1c579b1SScott Long 		}
2628f1c579b1SScott Long 		break;
2629ad6d6297SScott Long 	case ARCMSR_MESSAGE_CLEAR_RQBUFFER: {
2630ad6d6297SScott Long 			u_int8_t *pQbuffer = acb->rqbuffer;
2631ad6d6297SScott Long 
2632ad6d6297SScott Long 			if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
2633ad6d6297SScott Long 				acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
263444f05562SScott Long 				arcmsr_iop_message_read(acb);
263544f05562SScott Long 				/*signature, let IOP know data has been readed */
2636f1c579b1SScott Long 			}
2637ad6d6297SScott Long 			acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED;
2638ad6d6297SScott Long 			acb->rqbuf_firstindex = 0;
2639ad6d6297SScott Long 			acb->rqbuf_lastindex = 0;
2640f1c579b1SScott Long 			memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER);
2641ad6d6297SScott Long 			pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
2642ad6d6297SScott Long 			retvalue = ARCMSR_MESSAGE_SUCCESS;
2643f1c579b1SScott Long 		}
2644f1c579b1SScott Long 		break;
2645ad6d6297SScott Long 	case ARCMSR_MESSAGE_CLEAR_WQBUFFER:
2646f1c579b1SScott Long 		{
2647ad6d6297SScott Long 			u_int8_t *pQbuffer = acb->wqbuffer;
2648f1c579b1SScott Long 
2649ad6d6297SScott Long 			if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
2650ad6d6297SScott Long 				acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
265144f05562SScott Long 				arcmsr_iop_message_read(acb);
265244f05562SScott Long 				/*signature, let IOP know data has been readed */
2653f1c579b1SScott Long 			}
265444f05562SScott Long 			acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED|ACB_F_MESSAGE_WQBUFFER_READ);
2655ad6d6297SScott Long 			acb->wqbuf_firstindex = 0;
2656ad6d6297SScott Long 			acb->wqbuf_lastindex = 0;
2657f1c579b1SScott Long 			memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER);
2658ad6d6297SScott Long 			pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
2659ad6d6297SScott Long 			retvalue = ARCMSR_MESSAGE_SUCCESS;
2660f1c579b1SScott Long 		}
2661f1c579b1SScott Long 		break;
2662ad6d6297SScott Long 	case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER: {
2663ad6d6297SScott Long 			u_int8_t *pQbuffer;
2664f1c579b1SScott Long 
2665ad6d6297SScott Long 			if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
2666ad6d6297SScott Long 				acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
266744f05562SScott Long 				arcmsr_iop_message_read(acb);
266844f05562SScott Long 				/*signature, let IOP know data has been readed */
2669f1c579b1SScott Long 			}
2670ad6d6297SScott Long 			acb->acb_flags  |= (ACB_F_MESSAGE_WQBUFFER_CLEARED
2671ad6d6297SScott Long 					|ACB_F_MESSAGE_RQBUFFER_CLEARED
267244f05562SScott Long 					|ACB_F_MESSAGE_WQBUFFER_READ);
2673ad6d6297SScott Long 			acb->rqbuf_firstindex = 0;
2674ad6d6297SScott Long 			acb->rqbuf_lastindex = 0;
2675ad6d6297SScott Long 			acb->wqbuf_firstindex = 0;
2676ad6d6297SScott Long 			acb->wqbuf_lastindex = 0;
2677ad6d6297SScott Long 			pQbuffer = acb->rqbuffer;
2678ad6d6297SScott Long 			memset(pQbuffer, 0, sizeof(struct QBUFFER));
2679ad6d6297SScott Long 			pQbuffer = acb->wqbuffer;
2680ad6d6297SScott Long 			memset(pQbuffer, 0, sizeof(struct QBUFFER));
2681ad6d6297SScott Long 			pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
2682ad6d6297SScott Long 			retvalue = ARCMSR_MESSAGE_SUCCESS;
2683f1c579b1SScott Long 		}
2684f1c579b1SScott Long 		break;
2685ad6d6297SScott Long 	case ARCMSR_MESSAGE_REQUEST_RETURNCODE_3F: {
2686ad6d6297SScott Long 			pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_3F;
2687ad6d6297SScott Long 			retvalue = ARCMSR_MESSAGE_SUCCESS;
2688f1c579b1SScott Long 		}
2689f1c579b1SScott Long 		break;
2690ad6d6297SScott Long 	case ARCMSR_MESSAGE_SAY_HELLO: {
2691ad6d6297SScott Long 			u_int8_t *hello_string = "Hello! I am ARCMSR";
2692ad6d6297SScott Long 			u_int8_t *puserbuffer = (u_int8_t *)pcmdmessagefld->messagedatabuffer;
2693f1c579b1SScott Long 
2694ad6d6297SScott Long 			if(memcpy(puserbuffer, hello_string, (int16_t)strlen(hello_string))) {
2695ad6d6297SScott Long 				pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_ERROR;
2696ad6d6297SScott Long 				ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
2697f1c579b1SScott Long 				return ENOIOCTL;
2698f1c579b1SScott Long 			}
2699ad6d6297SScott Long 			pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
2700ad6d6297SScott Long 			retvalue = ARCMSR_MESSAGE_SUCCESS;
2701ad6d6297SScott Long 		}
2702ad6d6297SScott Long 		break;
2703ad6d6297SScott Long 	case ARCMSR_MESSAGE_SAY_GOODBYE: {
2704ad6d6297SScott Long 			arcmsr_iop_parking(acb);
2705ad6d6297SScott Long 			retvalue = ARCMSR_MESSAGE_SUCCESS;
2706ad6d6297SScott Long 		}
2707ad6d6297SScott Long 		break;
2708ad6d6297SScott Long 	case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE: {
2709ad6d6297SScott Long 			arcmsr_flush_adapter_cache(acb);
2710ad6d6297SScott Long 			retvalue = ARCMSR_MESSAGE_SUCCESS;
2711f1c579b1SScott Long 		}
2712f1c579b1SScott Long 		break;
2713f1c579b1SScott Long 	}
2714ad6d6297SScott Long 	ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
2715dac36688SXin LI 	return (retvalue);
2716f1c579b1SScott Long }
2717f1c579b1SScott Long /*
2718f1c579b1SScott Long **************************************************************************
2719f1c579b1SScott Long **************************************************************************
2720f1c579b1SScott Long */
272122f2616bSXin LI static void arcmsr_free_srb(struct CommandControlBlock *srb)
272222f2616bSXin LI {
272322f2616bSXin LI 	struct AdapterControlBlock	*acb;
272422f2616bSXin LI 
272522f2616bSXin LI 	acb = srb->acb;
27267a7bc959SXin LI 	ARCMSR_LOCK_ACQUIRE(&acb->srb_lock);
272722f2616bSXin LI 	srb->srb_state = ARCMSR_SRB_DONE;
272822f2616bSXin LI 	srb->srb_flags = 0;
272922f2616bSXin LI 	acb->srbworkingQ[acb->workingsrb_doneindex] = srb;
273022f2616bSXin LI 	acb->workingsrb_doneindex++;
273122f2616bSXin LI 	acb->workingsrb_doneindex %= ARCMSR_MAX_FREESRB_NUM;
27327a7bc959SXin LI 	ARCMSR_LOCK_RELEASE(&acb->srb_lock);
273322f2616bSXin LI }
273422f2616bSXin LI /*
273522f2616bSXin LI **************************************************************************
273622f2616bSXin LI **************************************************************************
273722f2616bSXin LI */
2738fc5ef1caSXin LI static struct CommandControlBlock *arcmsr_get_freesrb(struct AdapterControlBlock *acb)
2739f1c579b1SScott Long {
2740ad6d6297SScott Long 	struct CommandControlBlock *srb = NULL;
2741ad6d6297SScott Long 	u_int32_t workingsrb_startindex, workingsrb_doneindex;
2742f1c579b1SScott Long 
27437a7bc959SXin LI 	ARCMSR_LOCK_ACQUIRE(&acb->srb_lock);
2744ad6d6297SScott Long 	workingsrb_doneindex = acb->workingsrb_doneindex;
2745ad6d6297SScott Long 	workingsrb_startindex = acb->workingsrb_startindex;
2746ad6d6297SScott Long 	srb = acb->srbworkingQ[workingsrb_startindex];
2747ad6d6297SScott Long 	workingsrb_startindex++;
2748ad6d6297SScott Long 	workingsrb_startindex %= ARCMSR_MAX_FREESRB_NUM;
2749ad6d6297SScott Long 	if(workingsrb_doneindex != workingsrb_startindex) {
2750ad6d6297SScott Long 		acb->workingsrb_startindex = workingsrb_startindex;
2751ad6d6297SScott Long 	} else {
2752ad6d6297SScott Long 		srb = NULL;
2753ad6d6297SScott Long 	}
27547a7bc959SXin LI 	ARCMSR_LOCK_RELEASE(&acb->srb_lock);
2755ad6d6297SScott Long 	return(srb);
2756ad6d6297SScott Long }
2757ad6d6297SScott Long /*
2758ad6d6297SScott Long **************************************************************************
2759ad6d6297SScott Long **************************************************************************
2760ad6d6297SScott Long */
2761ad6d6297SScott Long static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb *pccb)
2762ad6d6297SScott Long {
2763ad6d6297SScott Long 	struct CMD_MESSAGE_FIELD *pcmdmessagefld;
2764ad6d6297SScott Long 	int retvalue = 0, transfer_len = 0;
2765ad6d6297SScott Long 	char *buffer;
27664aa947cbSWarner Losh 	uint8_t *ptr = scsiio_cdb_ptr(&pccb->csio);
27674aa947cbSWarner Losh 	u_int32_t controlcode = (u_int32_t ) ptr[5] << 24 |
27684aa947cbSWarner Losh 				(u_int32_t ) ptr[6] << 16 |
27694aa947cbSWarner Losh 				(u_int32_t ) ptr[7] << 8  |
27704aa947cbSWarner Losh 				(u_int32_t ) ptr[8];
2771ad6d6297SScott Long 					/* 4 bytes: Areca io control code */
2772dd0b4fb6SKonstantin Belousov 	if ((pccb->ccb_h.flags & CAM_DATA_MASK) == CAM_DATA_VADDR) {
2773ad6d6297SScott Long 		buffer = pccb->csio.data_ptr;
2774ad6d6297SScott Long 		transfer_len = pccb->csio.dxfer_len;
2775ad6d6297SScott Long 	} else {
2776ad6d6297SScott Long 		retvalue = ARCMSR_MESSAGE_FAIL;
2777ad6d6297SScott Long 		goto message_out;
2778ad6d6297SScott Long 	}
2779ad6d6297SScott Long 	if (transfer_len > sizeof(struct CMD_MESSAGE_FIELD)) {
2780ad6d6297SScott Long 		retvalue = ARCMSR_MESSAGE_FAIL;
2781ad6d6297SScott Long 		goto message_out;
2782ad6d6297SScott Long 	}
2783ad6d6297SScott Long 	pcmdmessagefld = (struct CMD_MESSAGE_FIELD *) buffer;
2784ad6d6297SScott Long 	switch(controlcode) {
2785ad6d6297SScott Long 	case ARCMSR_MESSAGE_READ_RQBUFFER: {
2786ad6d6297SScott Long 			u_int8_t *pQbuffer;
2787ad6d6297SScott Long 			u_int8_t *ptmpQbuffer = pcmdmessagefld->messagedatabuffer;
2788ad6d6297SScott Long 			int32_t allxfer_len = 0;
2789f1c579b1SScott Long 
27907a7bc959SXin LI 			ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
2791ad6d6297SScott Long 			while ((acb->rqbuf_firstindex != acb->rqbuf_lastindex)
2792ad6d6297SScott Long 				&& (allxfer_len < 1031)) {
2793ad6d6297SScott Long 				pQbuffer = &acb->rqbuffer[acb->rqbuf_firstindex];
27947a7bc959SXin LI 				*ptmpQbuffer = *pQbuffer;
2795ad6d6297SScott Long 				acb->rqbuf_firstindex++;
2796ad6d6297SScott Long 				acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER;
2797ad6d6297SScott Long 				ptmpQbuffer++;
2798ad6d6297SScott Long 				allxfer_len++;
2799f1c579b1SScott Long 			}
2800ad6d6297SScott Long 			if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
280144f05562SScott Long 				struct QBUFFER  *prbuffer;
2802ad6d6297SScott Long 
2803ad6d6297SScott Long 				acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
280444f05562SScott Long 				prbuffer = arcmsr_get_iop_rqbuffer(acb);
280535689395SXin LI 				if(arcmsr_Read_iop_rqbuffer_data(acb, prbuffer) == 0)
280635689395SXin LI 					acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW;
2807ad6d6297SScott Long 			}
2808ad6d6297SScott Long 			pcmdmessagefld->cmdmessage.Length = allxfer_len;
2809ad6d6297SScott Long 			pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
2810ad6d6297SScott Long 			retvalue = ARCMSR_MESSAGE_SUCCESS;
28117a7bc959SXin LI 			ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
2812ad6d6297SScott Long 		}
2813ad6d6297SScott Long 		break;
2814ad6d6297SScott Long 	case ARCMSR_MESSAGE_WRITE_WQBUFFER: {
2815ad6d6297SScott Long 			int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex;
2816ad6d6297SScott Long 			u_int8_t *pQbuffer;
2817ad6d6297SScott Long 			u_int8_t *ptmpuserbuffer = pcmdmessagefld->messagedatabuffer;
2818ad6d6297SScott Long 
2819ad6d6297SScott Long 			user_len = pcmdmessagefld->cmdmessage.Length;
28207a7bc959SXin LI 			ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
2821ad6d6297SScott Long 			wqbuf_lastindex = acb->wqbuf_lastindex;
2822ad6d6297SScott Long 			wqbuf_firstindex = acb->wqbuf_firstindex;
2823ad6d6297SScott Long 			if (wqbuf_lastindex != wqbuf_firstindex) {
28247a7bc959SXin LI 				arcmsr_Write_data_2iop_wqbuffer(acb);
2825ad6d6297SScott Long 				/* has error report sensedata */
2826dac36688SXin LI 				if(pccb->csio.sense_len) {
2827ad6d6297SScott Long 				((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70);
2828ad6d6297SScott Long 				/* Valid,ErrorCode */
2829ad6d6297SScott Long 				((u_int8_t *)&pccb->csio.sense_data)[2] = 0x05;
2830ad6d6297SScott Long 				/* FileMark,EndOfMedia,IncorrectLength,Reserved,SenseKey */
2831ad6d6297SScott Long 				((u_int8_t *)&pccb->csio.sense_data)[7] = 0x0A;
2832ad6d6297SScott Long 				/* AdditionalSenseLength */
2833ad6d6297SScott Long 				((u_int8_t *)&pccb->csio.sense_data)[12] = 0x20;
2834ad6d6297SScott Long 				/* AdditionalSenseCode */
2835ad6d6297SScott Long 				}
2836ad6d6297SScott Long 				retvalue = ARCMSR_MESSAGE_FAIL;
2837ad6d6297SScott Long 			} else {
2838ad6d6297SScott Long 				my_empty_len = (wqbuf_firstindex-wqbuf_lastindex - 1)
2839ad6d6297SScott Long 						&(ARCMSR_MAX_QBUFFER - 1);
2840ad6d6297SScott Long 				if (my_empty_len >= user_len) {
2841ad6d6297SScott Long 					while (user_len > 0) {
2842ad6d6297SScott Long 						pQbuffer = &acb->wqbuffer[acb->wqbuf_lastindex];
28437a7bc959SXin LI 						*pQbuffer = *ptmpuserbuffer;
2844ad6d6297SScott Long 						acb->wqbuf_lastindex++;
2845ad6d6297SScott Long 						acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER;
2846ad6d6297SScott Long 						ptmpuserbuffer++;
2847ad6d6297SScott Long 						user_len--;
2848ad6d6297SScott Long 					}
2849ad6d6297SScott Long 					if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) {
2850ad6d6297SScott Long 						acb->acb_flags &=
2851ad6d6297SScott Long 						    ~ACB_F_MESSAGE_WQBUFFER_CLEARED;
28527a7bc959SXin LI 						arcmsr_Write_data_2iop_wqbuffer(acb);
2853ad6d6297SScott Long 					}
2854ad6d6297SScott Long 				} else {
2855ad6d6297SScott Long 					/* has error report sensedata */
2856dac36688SXin LI 					if(pccb->csio.sense_len) {
2857ad6d6297SScott Long 					((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70);
2858ad6d6297SScott Long 					/* Valid,ErrorCode */
2859ad6d6297SScott Long 					((u_int8_t *)&pccb->csio.sense_data)[2] = 0x05;
2860ad6d6297SScott Long 					/* FileMark,EndOfMedia,IncorrectLength,Reserved,SenseKey */
2861ad6d6297SScott Long 					((u_int8_t *)&pccb->csio.sense_data)[7] = 0x0A;
2862ad6d6297SScott Long 					/* AdditionalSenseLength */
2863ad6d6297SScott Long 					((u_int8_t *)&pccb->csio.sense_data)[12] = 0x20;
2864ad6d6297SScott Long 					/* AdditionalSenseCode */
2865ad6d6297SScott Long 					}
2866ad6d6297SScott Long 					retvalue = ARCMSR_MESSAGE_FAIL;
2867ad6d6297SScott Long 				}
2868ad6d6297SScott Long 			}
28697a7bc959SXin LI 			ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
2870ad6d6297SScott Long 		}
2871ad6d6297SScott Long 		break;
2872ad6d6297SScott Long 	case ARCMSR_MESSAGE_CLEAR_RQBUFFER: {
2873ad6d6297SScott Long 			u_int8_t *pQbuffer = acb->rqbuffer;
2874ad6d6297SScott Long 
28757a7bc959SXin LI 			ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
2876ad6d6297SScott Long 			if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
2877ad6d6297SScott Long 				acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
287844f05562SScott Long 				arcmsr_iop_message_read(acb);
2879ad6d6297SScott Long 			}
2880ad6d6297SScott Long 			acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED;
2881ad6d6297SScott Long 			acb->rqbuf_firstindex = 0;
2882ad6d6297SScott Long 			acb->rqbuf_lastindex = 0;
2883ad6d6297SScott Long 			memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER);
2884ad6d6297SScott Long 			pcmdmessagefld->cmdmessage.ReturnCode =
2885ad6d6297SScott Long 			    ARCMSR_MESSAGE_RETURNCODE_OK;
28867a7bc959SXin LI 			ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
2887ad6d6297SScott Long 		}
2888ad6d6297SScott Long 		break;
2889ad6d6297SScott Long 	case ARCMSR_MESSAGE_CLEAR_WQBUFFER: {
2890ad6d6297SScott Long 			u_int8_t *pQbuffer = acb->wqbuffer;
2891ad6d6297SScott Long 
28927a7bc959SXin LI 			ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
2893ad6d6297SScott Long 			if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
2894ad6d6297SScott Long 				acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
289544f05562SScott Long 				arcmsr_iop_message_read(acb);
2896ad6d6297SScott Long 			}
2897ad6d6297SScott Long 			acb->acb_flags |=
2898ad6d6297SScott Long 				(ACB_F_MESSAGE_WQBUFFER_CLEARED |
289944f05562SScott Long 					ACB_F_MESSAGE_WQBUFFER_READ);
2900ad6d6297SScott Long 			acb->wqbuf_firstindex = 0;
2901ad6d6297SScott Long 			acb->wqbuf_lastindex = 0;
2902ad6d6297SScott Long 			memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER);
2903ad6d6297SScott Long 			pcmdmessagefld->cmdmessage.ReturnCode =
2904ad6d6297SScott Long 				ARCMSR_MESSAGE_RETURNCODE_OK;
29057a7bc959SXin LI 			ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
2906ad6d6297SScott Long 		}
2907ad6d6297SScott Long 		break;
2908ad6d6297SScott Long 	case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER: {
2909ad6d6297SScott Long 			u_int8_t *pQbuffer;
2910ad6d6297SScott Long 
29117a7bc959SXin LI 			ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
2912ad6d6297SScott Long 			if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
2913ad6d6297SScott Long 				acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
291444f05562SScott Long 				arcmsr_iop_message_read(acb);
2915ad6d6297SScott Long 			}
2916ad6d6297SScott Long 			acb->acb_flags |=
2917ad6d6297SScott Long 				(ACB_F_MESSAGE_WQBUFFER_CLEARED
2918ad6d6297SScott Long 				| ACB_F_MESSAGE_RQBUFFER_CLEARED
291944f05562SScott Long 				| ACB_F_MESSAGE_WQBUFFER_READ);
2920ad6d6297SScott Long 			acb->rqbuf_firstindex = 0;
2921ad6d6297SScott Long 			acb->rqbuf_lastindex = 0;
2922ad6d6297SScott Long 			acb->wqbuf_firstindex = 0;
2923ad6d6297SScott Long 			acb->wqbuf_lastindex = 0;
2924ad6d6297SScott Long 			pQbuffer = acb->rqbuffer;
2925ad6d6297SScott Long 			memset(pQbuffer, 0, sizeof (struct QBUFFER));
2926ad6d6297SScott Long 			pQbuffer = acb->wqbuffer;
2927ad6d6297SScott Long 			memset(pQbuffer, 0, sizeof (struct QBUFFER));
2928ad6d6297SScott Long 			pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
29297a7bc959SXin LI 			ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
2930ad6d6297SScott Long 		}
2931ad6d6297SScott Long 		break;
2932ad6d6297SScott Long 	case ARCMSR_MESSAGE_REQUEST_RETURNCODE_3F: {
2933ad6d6297SScott Long 			pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_3F;
2934ad6d6297SScott Long 		}
2935ad6d6297SScott Long 		break;
2936ad6d6297SScott Long 	case ARCMSR_MESSAGE_SAY_HELLO: {
2937ad6d6297SScott Long 			int8_t *hello_string = "Hello! I am ARCMSR";
2938ad6d6297SScott Long 
2939ad6d6297SScott Long 			memcpy(pcmdmessagefld->messagedatabuffer, hello_string
2940ad6d6297SScott Long 				, (int16_t)strlen(hello_string));
2941ad6d6297SScott Long 			pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
2942ad6d6297SScott Long 		}
2943ad6d6297SScott Long 		break;
2944ad6d6297SScott Long 	case ARCMSR_MESSAGE_SAY_GOODBYE:
2945ad6d6297SScott Long 		arcmsr_iop_parking(acb);
2946ad6d6297SScott Long 		break;
2947ad6d6297SScott Long 	case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE:
2948ad6d6297SScott Long 		arcmsr_flush_adapter_cache(acb);
2949ad6d6297SScott Long 		break;
2950ad6d6297SScott Long 	default:
2951ad6d6297SScott Long 		retvalue = ARCMSR_MESSAGE_FAIL;
2952ad6d6297SScott Long 	}
2953ad6d6297SScott Long message_out:
2954dac36688SXin LI 	return (retvalue);
2955f1c579b1SScott Long }
2956f1c579b1SScott Long /*
2957f1c579b1SScott Long *********************************************************************
2958f1c579b1SScott Long *********************************************************************
2959f1c579b1SScott Long */
2960231c8b71SXin LI static void arcmsr_execute_srb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
2961f1c579b1SScott Long {
2962ad6d6297SScott Long 	struct CommandControlBlock *srb = (struct CommandControlBlock *)arg;
2963ad6d6297SScott Long 	struct AdapterControlBlock *acb = (struct AdapterControlBlock *)srb->acb;
2964f1c579b1SScott Long 	union ccb *pccb;
2965ad6d6297SScott Long 	int target, lun;
2966f1c579b1SScott Long 
2967ad6d6297SScott Long 	pccb = srb->pccb;
2968ad6d6297SScott Long 	target = pccb->ccb_h.target_id;
2969ad6d6297SScott Long 	lun = pccb->ccb_h.target_lun;
297022f2616bSXin LI 	acb->pktRequestCount++;
2971ad6d6297SScott Long 	if(error != 0) {
2972ad6d6297SScott Long 		if(error != EFBIG) {
297344f05562SScott Long 			printf("arcmsr%d: unexpected error %x"
297444f05562SScott Long 				" returned from 'bus_dmamap_load' \n"
2975ad6d6297SScott Long 				, acb->pci_unit, error);
2976f1c579b1SScott Long 		}
2977ad6d6297SScott Long 		if((pccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) {
297815735becSScott Long 			pccb->ccb_h.status |= CAM_REQ_TOO_BIG;
2979f1c579b1SScott Long 		}
2980ad6d6297SScott Long 		arcmsr_srb_complete(srb, 0);
2981f1c579b1SScott Long 		return;
2982f1c579b1SScott Long 	}
2983ad6d6297SScott Long 	if(nseg > ARCMSR_MAX_SG_ENTRIES) {
2984ad6d6297SScott Long 		pccb->ccb_h.status |= CAM_REQ_TOO_BIG;
2985ad6d6297SScott Long 		arcmsr_srb_complete(srb, 0);
2986ad6d6297SScott Long 		return;
2987f1c579b1SScott Long 	}
2988ad6d6297SScott Long 	if(acb->acb_flags & ACB_F_BUS_RESET) {
2989ad6d6297SScott Long 		printf("arcmsr%d: bus reset and return busy \n", acb->pci_unit);
2990ad6d6297SScott Long 		pccb->ccb_h.status |= CAM_SCSI_BUS_RESET;
2991ad6d6297SScott Long 		arcmsr_srb_complete(srb, 0);
2992ad6d6297SScott Long 		return;
2993ad6d6297SScott Long 	}
2994ad6d6297SScott Long 	if(acb->devstate[target][lun] == ARECA_RAID_GONE) {
299522f2616bSXin LI 		u_int8_t block_cmd, cmd;
2996ad6d6297SScott Long 
29974aa947cbSWarner Losh 		cmd = scsiio_cdb_ptr(&pccb->csio)[0];
299822f2616bSXin LI 		block_cmd = cmd & 0x0f;
2999ad6d6297SScott Long 		if(block_cmd == 0x08 || block_cmd == 0x0a) {
3000ad6d6297SScott Long 			printf("arcmsr%d:block 'read/write' command "
300122f2616bSXin LI 				"with gone raid volume Cmd=0x%2x, TargetId=%d, Lun=%d \n"
300222f2616bSXin LI 				, acb->pci_unit, cmd, target, lun);
3003ad6d6297SScott Long 			pccb->ccb_h.status |= CAM_DEV_NOT_THERE;
3004ad6d6297SScott Long 			arcmsr_srb_complete(srb, 0);
3005ad6d6297SScott Long 			return;
3006ad6d6297SScott Long 		}
3007ad6d6297SScott Long 	}
3008ad6d6297SScott Long 	if((pccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_INPROG) {
3009ad6d6297SScott Long 		if(nseg != 0) {
3010ad6d6297SScott Long 			bus_dmamap_unload(acb->dm_segs_dmat, srb->dm_segs_dmamap);
3011ad6d6297SScott Long 		}
3012ad6d6297SScott Long 		arcmsr_srb_complete(srb, 0);
3013f1c579b1SScott Long 		return;
3014f1c579b1SScott Long 	}
3015abfdbca9SXin LI 	if(acb->srboutstandingcount >= acb->maxOutstanding) {
30167a7bc959SXin LI 		if((acb->acb_flags & ACB_F_CAM_DEV_QFRZN) == 0)
30177a7bc959SXin LI 		{
301815735becSScott Long 			xpt_freeze_simq(acb->psim, 1);
3019dc3a205bSScott Long 			acb->acb_flags |= ACB_F_CAM_DEV_QFRZN;
30207a7bc959SXin LI 		}
30217a7bc959SXin LI 		pccb->ccb_h.status &= ~CAM_SIM_QUEUED;
30227a7bc959SXin LI 		pccb->ccb_h.status |= CAM_REQUEUE_REQ;
3023ad6d6297SScott Long 		arcmsr_srb_complete(srb, 0);
3024ad6d6297SScott Long 		return;
3025f1c579b1SScott Long 	}
302615735becSScott Long 	pccb->ccb_h.status |= CAM_SIM_QUEUED;
3027ad6d6297SScott Long 	arcmsr_build_srb(srb, dm_segs, nseg);
3028ad6d6297SScott Long 	arcmsr_post_srb(acb, srb);
302922f2616bSXin LI 	if (pccb->ccb_h.timeout != CAM_TIME_INFINITY)
303022f2616bSXin LI 	{
303122f2616bSXin LI 		arcmsr_callout_init(&srb->ccb_callout);
303285c9dd9dSSteven Hartland 		callout_reset_sbt(&srb->ccb_callout, SBT_1MS *
303385c9dd9dSSteven Hartland 		    (pccb->ccb_h.timeout + (ARCMSR_TIMEOUT_DELAY * 1000)), 0,
303485c9dd9dSSteven Hartland 		    arcmsr_srb_timeout, srb, 0);
303522f2616bSXin LI 		srb->srb_flags |= SRB_FLAG_TIMER_START;
303622f2616bSXin LI 	}
3037f1c579b1SScott Long }
3038f1c579b1SScott Long /*
3039f1c579b1SScott Long *****************************************************************************************
3040f1c579b1SScott Long *****************************************************************************************
3041f1c579b1SScott Long */
3042ad6d6297SScott Long static u_int8_t arcmsr_seek_cmd2abort(union ccb *abortccb)
3043f1c579b1SScott Long {
3044ad6d6297SScott Long 	struct CommandControlBlock *srb;
3045ad6d6297SScott Long 	struct AdapterControlBlock *acb = (struct AdapterControlBlock *) abortccb->ccb_h.arcmsr_ccbacb_ptr;
304644f05562SScott Long 	u_int32_t intmask_org;
3047ad6d6297SScott Long 	int i = 0;
3048f1c579b1SScott Long 
3049ad6d6297SScott Long 	acb->num_aborts++;
3050f1c579b1SScott Long 	/*
3051ad6d6297SScott Long 	***************************************************************************
3052f1c579b1SScott Long 	** It is the upper layer do abort command this lock just prior to calling us.
3053f1c579b1SScott Long 	** First determine if we currently own this command.
3054f1c579b1SScott Long 	** Start by searching the device queue. If not found
3055f1c579b1SScott Long 	** at all, and the system wanted us to just abort the
3056f1c579b1SScott Long 	** command return success.
3057ad6d6297SScott Long 	***************************************************************************
3058f1c579b1SScott Long 	*/
3059ad6d6297SScott Long 	if(acb->srboutstandingcount != 0) {
306022f2616bSXin LI 		/* disable all outbound interrupt */
306122f2616bSXin LI 		intmask_org = arcmsr_disable_allintr(acb);
3062ad6d6297SScott Long 		for(i=0; i < ARCMSR_MAX_FREESRB_NUM; i++) {
3063ad6d6297SScott Long 			srb = acb->psrb_pool[i];
306422f2616bSXin LI 			if(srb->srb_state == ARCMSR_SRB_START) {
3065ad6d6297SScott Long 				if(srb->pccb == abortccb) {
306622f2616bSXin LI 					srb->srb_state = ARCMSR_SRB_ABORTED;
3067123055f0SNathan Whitehorn 					printf("arcmsr%d:scsi id=%d lun=%jx abort srb '%p'"
3068ad6d6297SScott Long 						"outstanding command \n"
3069ad6d6297SScott Long 						, acb->pci_unit, abortccb->ccb_h.target_id
3070123055f0SNathan Whitehorn 						, (uintmax_t)abortccb->ccb_h.target_lun, srb);
3071ad6d6297SScott Long 					arcmsr_polling_srbdone(acb, srb);
307244f05562SScott Long 					/* enable outbound Post Queue, outbound doorbell Interrupt */
307344f05562SScott Long 					arcmsr_enable_allintr(acb, intmask_org);
3074ad6d6297SScott Long 					return (TRUE);
3075f1c579b1SScott Long 				}
307622f2616bSXin LI 			}
307722f2616bSXin LI 		}
307822f2616bSXin LI 		/* enable outbound Post Queue, outbound doorbell Interrupt */
307922f2616bSXin LI 		arcmsr_enable_allintr(acb, intmask_org);
308022f2616bSXin LI 	}
308122f2616bSXin LI 	return(FALSE);
308222f2616bSXin LI }
3083f1c579b1SScott Long /*
3084f1c579b1SScott Long ****************************************************************************
3085f1c579b1SScott Long ****************************************************************************
3086f1c579b1SScott Long */
3087ad6d6297SScott Long static void arcmsr_bus_reset(struct AdapterControlBlock *acb)
3088f1c579b1SScott Long {
3089ad6d6297SScott Long 	int retry = 0;
3090f1c579b1SScott Long 
3091ad6d6297SScott Long 	acb->num_resets++;
3092ad6d6297SScott Long 	acb->acb_flags |= ACB_F_BUS_RESET;
3093ad6d6297SScott Long 	while(acb->srboutstandingcount != 0 && retry < 400) {
309444f05562SScott Long 		arcmsr_interrupt(acb);
3095ad6d6297SScott Long 		UDELAY(25000);
3096ad6d6297SScott Long 		retry++;
3097ad6d6297SScott Long 	}
3098ad6d6297SScott Long 	arcmsr_iop_reset(acb);
3099ad6d6297SScott Long 	acb->acb_flags &= ~ACB_F_BUS_RESET;
3100f1c579b1SScott Long }
3101f1c579b1SScott Long /*
3102ad6d6297SScott Long **************************************************************************
3103ad6d6297SScott Long **************************************************************************
3104ad6d6297SScott Long */
3105ad6d6297SScott Long static void arcmsr_handle_virtual_command(struct AdapterControlBlock *acb,
3106ad6d6297SScott Long 		union ccb *pccb)
3107ad6d6297SScott Long {
3108ad6d6297SScott Long 	if (pccb->ccb_h.target_lun) {
310961ba2ac6SJim Harris 		pccb->ccb_h.status |= CAM_DEV_NOT_THERE;
3110ad6d6297SScott Long 		xpt_done(pccb);
3111ad6d6297SScott Long 		return;
3112ad6d6297SScott Long 	}
31137a7bc959SXin LI 	pccb->ccb_h.status |= CAM_REQ_CMP;
31144aa947cbSWarner Losh 	switch (scsiio_cdb_ptr(&pccb->csio)[0]) {
31157a7bc959SXin LI 	case INQUIRY: {
31167a7bc959SXin LI 		unsigned char inqdata[36];
31177a7bc959SXin LI 		char *buffer = pccb->csio.data_ptr;
31187a7bc959SXin LI 
3119231c8b71SXin LI 		inqdata[0] = T_PROCESSOR;	/* Periph Qualifier & Periph Dev Type */
3120231c8b71SXin LI 		inqdata[1] = 0;			/* rem media bit & Dev Type Modifier */
3121231c8b71SXin LI 		inqdata[2] = 0;			/* ISO, ECMA, & ANSI versions */
3122231c8b71SXin LI 		inqdata[3] = 0;
3123231c8b71SXin LI 		inqdata[4] = 31;		/* length of additional data */
3124231c8b71SXin LI 		inqdata[5] = 0;
3125231c8b71SXin LI 		inqdata[6] = 0;
3126231c8b71SXin LI 		inqdata[7] = 0;
3127231c8b71SXin LI 		strncpy(&inqdata[8], "Areca   ", 8);	/* Vendor Identification */
3128231c8b71SXin LI 		strncpy(&inqdata[16], "RAID controller ", 16);	/* Product Identification */
3129ad6d6297SScott Long 		strncpy(&inqdata[32], "R001", 4); /* Product Revision */
3130ad6d6297SScott Long 		memcpy(buffer, inqdata, sizeof(inqdata));
3131ad6d6297SScott Long 		xpt_done(pccb);
3132ad6d6297SScott Long 	}
3133ad6d6297SScott Long 	break;
3134ad6d6297SScott Long 	case WRITE_BUFFER:
3135ad6d6297SScott Long 	case READ_BUFFER: {
3136ad6d6297SScott Long 		if (arcmsr_iop_message_xfer(acb, pccb)) {
3137ad6d6297SScott Long 			pccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
3138ad6d6297SScott Long 			pccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
3139ad6d6297SScott Long 		}
3140ad6d6297SScott Long 		xpt_done(pccb);
3141ad6d6297SScott Long 	}
3142ad6d6297SScott Long 	break;
3143ad6d6297SScott Long 	default:
3144ad6d6297SScott Long 		xpt_done(pccb);
3145ad6d6297SScott Long 	}
3146ad6d6297SScott Long }
3147ad6d6297SScott Long /*
3148f1c579b1SScott Long *********************************************************************
3149f1c579b1SScott Long *********************************************************************
3150f1c579b1SScott Long */
3151ad6d6297SScott Long static void arcmsr_action(struct cam_sim *psim, union ccb *pccb)
3152f1c579b1SScott Long {
3153ad6d6297SScott Long 	struct AdapterControlBlock *acb;
3154f1c579b1SScott Long 
3155ad6d6297SScott Long 	acb = (struct AdapterControlBlock *) cam_sim_softc(psim);
3156ad6d6297SScott Long 	if(acb == NULL) {
3157ad6d6297SScott Long 		pccb->ccb_h.status |= CAM_REQ_INVALID;
3158f1c579b1SScott Long 		xpt_done(pccb);
3159f1c579b1SScott Long 		return;
3160f1c579b1SScott Long 	}
3161ad6d6297SScott Long 	switch (pccb->ccb_h.func_code) {
3162ad6d6297SScott Long 	case XPT_SCSI_IO: {
3163ad6d6297SScott Long 			struct CommandControlBlock *srb;
3164ad6d6297SScott Long 			int target = pccb->ccb_h.target_id;
3165dd0b4fb6SKonstantin Belousov 			int error;
3166f1c579b1SScott Long 
31674aa947cbSWarner Losh 			if (pccb->ccb_h.flags & CAM_CDB_PHYS) {
31684aa947cbSWarner Losh 				pccb->ccb_h.status = CAM_REQ_INVALID;
31694aa947cbSWarner Losh 				xpt_done(pccb);
31704aa947cbSWarner Losh 				return;
31714aa947cbSWarner Losh 			}
31724aa947cbSWarner Losh 
3173ad6d6297SScott Long 			if(target == 16) {
3174ad6d6297SScott Long 				/* virtual device for iop message transfer */
3175ad6d6297SScott Long 				arcmsr_handle_virtual_command(acb, pccb);
3176ad6d6297SScott Long 				return;
3177ad6d6297SScott Long 			}
3178ad6d6297SScott Long 			if((srb = arcmsr_get_freesrb(acb)) == NULL) {
3179ad6d6297SScott Long 				pccb->ccb_h.status |= CAM_RESRC_UNAVAIL;
3180f1c579b1SScott Long 				xpt_done(pccb);
3181f1c579b1SScott Long 				return;
3182f1c579b1SScott Long 			}
3183ad6d6297SScott Long 			pccb->ccb_h.arcmsr_ccbsrb_ptr = srb;
3184ad6d6297SScott Long 			pccb->ccb_h.arcmsr_ccbacb_ptr = acb;
3185ad6d6297SScott Long 			srb->pccb = pccb;
3186dd0b4fb6SKonstantin Belousov 			error =	bus_dmamap_load_ccb(acb->dm_segs_dmat
3187ad6d6297SScott Long 				, srb->dm_segs_dmamap
3188dd0b4fb6SKonstantin Belousov 				, pccb
3189231c8b71SXin LI 				, arcmsr_execute_srb, srb, /*flags*/0);
3190ad6d6297SScott Long 			if(error == EINPROGRESS) {
3191ad6d6297SScott Long 				xpt_freeze_simq(acb->psim, 1);
3192f1c579b1SScott Long 				pccb->ccb_h.status |= CAM_RELEASE_SIMQ;
3193f1c579b1SScott Long 			}
3194f1c579b1SScott Long 			break;
3195f1c579b1SScott Long 		}
3196ad6d6297SScott Long 	case XPT_PATH_INQ: {
3197f1c579b1SScott Long 			struct ccb_pathinq *cpi = &pccb->cpi;
3198f1c579b1SScott Long 
3199f1c579b1SScott Long 			cpi->version_num = 1;
3200f1c579b1SScott Long 			cpi->hba_inquiry = PI_SDTR_ABLE | PI_TAG_ABLE;
3201f1c579b1SScott Long 			cpi->target_sprt = 0;
3202f1c579b1SScott Long 			cpi->hba_misc = 0;
3203f1c579b1SScott Long 			cpi->hba_eng_cnt = 0;
3204ad6d6297SScott Long 			cpi->max_target = ARCMSR_MAX_TARGETID;        /* 0-16 */
3205ad6d6297SScott Long 			cpi->max_lun = ARCMSR_MAX_TARGETLUN;	    /* 0-7 */
3206ad6d6297SScott Long 			cpi->initiator_id = ARCMSR_SCSI_INITIATOR_ID; /* 255 */
3207f1c579b1SScott Long 			cpi->bus_id = cam_sim_bus(psim);
32084195c7deSAlan Somers 			strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
32094195c7deSAlan Somers 			strlcpy(cpi->hba_vid, "ARCMSR", HBA_IDLEN);
32104195c7deSAlan Somers 			strlcpy(cpi->dev_name, cam_sim_name(psim), DEV_IDLEN);
3211f1c579b1SScott Long 			cpi->unit_number = cam_sim_unit(psim);
3212224a78aeSXin LI 			if(acb->adapter_bus_speed == ACB_BUS_SPEED_12G)
3213224a78aeSXin LI 				cpi->base_transfer_speed = 1200000;
3214224a78aeSXin LI 			else if(acb->adapter_bus_speed == ACB_BUS_SPEED_6G)
3215dac36688SXin LI 				cpi->base_transfer_speed = 600000;
3216dac36688SXin LI 			else
3217dac36688SXin LI 				cpi->base_transfer_speed = 300000;
3218dac36688SXin LI 			if((acb->vendor_device_id == PCIDevVenIDARC1880) ||
3219a1103e04SXin LI 			   (acb->vendor_device_id == PCIDevVenIDARC1884) ||
32207a7bc959SXin LI 			   (acb->vendor_device_id == PCIDevVenIDARC1680) ||
32217a7bc959SXin LI 			   (acb->vendor_device_id == PCIDevVenIDARC1214))
3222dac36688SXin LI 			{
3223dac36688SXin LI 				cpi->transport = XPORT_SAS;
3224dac36688SXin LI 				cpi->transport_version = 0;
3225dac36688SXin LI 				cpi->protocol_version = SCSI_REV_SPC2;
3226dac36688SXin LI 			}
3227dac36688SXin LI 			else
3228dac36688SXin LI 			{
3229fa9ed865SMatt Jacob 				cpi->transport = XPORT_SPI;
3230fa9ed865SMatt Jacob 				cpi->transport_version = 2;
3231fa9ed865SMatt Jacob 				cpi->protocol_version = SCSI_REV_2;
3232dac36688SXin LI 			}
3233dac36688SXin LI 			cpi->protocol = PROTO_SCSI;
3234ad6d6297SScott Long 			cpi->ccb_h.status |= CAM_REQ_CMP;
3235f1c579b1SScott Long 			xpt_done(pccb);
3236f1c579b1SScott Long 			break;
3237f1c579b1SScott Long 		}
3238ad6d6297SScott Long 	case XPT_ABORT: {
3239f1c579b1SScott Long 			union ccb *pabort_ccb;
3240f1c579b1SScott Long 
3241f1c579b1SScott Long 			pabort_ccb = pccb->cab.abort_ccb;
3242ad6d6297SScott Long 			switch (pabort_ccb->ccb_h.func_code) {
3243f1c579b1SScott Long 			case XPT_ACCEPT_TARGET_IO:
3244f1c579b1SScott Long 			case XPT_CONT_TARGET_IO:
3245ad6d6297SScott Long 				if(arcmsr_seek_cmd2abort(pabort_ccb)==TRUE) {
3246ad6d6297SScott Long 					pabort_ccb->ccb_h.status |= CAM_REQ_ABORTED;
3247f1c579b1SScott Long 					xpt_done(pabort_ccb);
3248ad6d6297SScott Long 					pccb->ccb_h.status |= CAM_REQ_CMP;
3249ad6d6297SScott Long 				} else {
3250f1c579b1SScott Long 					xpt_print_path(pabort_ccb->ccb_h.path);
3251f1c579b1SScott Long 					printf("Not found\n");
3252ad6d6297SScott Long 					pccb->ccb_h.status |= CAM_PATH_INVALID;
3253f1c579b1SScott Long 				}
3254f1c579b1SScott Long 				break;
3255f1c579b1SScott Long 			case XPT_SCSI_IO:
3256ad6d6297SScott Long 				pccb->ccb_h.status |= CAM_UA_ABORT;
3257f1c579b1SScott Long 				break;
3258f1c579b1SScott Long 			default:
3259ad6d6297SScott Long 				pccb->ccb_h.status |= CAM_REQ_INVALID;
3260f1c579b1SScott Long 				break;
3261f1c579b1SScott Long 			}
3262f1c579b1SScott Long 			xpt_done(pccb);
3263f1c579b1SScott Long 			break;
3264f1c579b1SScott Long 		}
3265f1c579b1SScott Long 	case XPT_RESET_BUS:
3266ad6d6297SScott Long 	case XPT_RESET_DEV: {
3267ad6d6297SScott Long 			u_int32_t	i;
3268f1c579b1SScott Long 
3269ad6d6297SScott Long 			arcmsr_bus_reset(acb);
3270ad6d6297SScott Long 			for (i=0; i < 500; i++) {
3271f1c579b1SScott Long 				DELAY(1000);
3272f1c579b1SScott Long 			}
3273ad6d6297SScott Long 			pccb->ccb_h.status |= CAM_REQ_CMP;
3274f1c579b1SScott Long 			xpt_done(pccb);
3275f1c579b1SScott Long 			break;
3276f1c579b1SScott Long 		}
3277ad6d6297SScott Long 	case XPT_TERM_IO: {
3278ad6d6297SScott Long 			pccb->ccb_h.status |= CAM_REQ_INVALID;
3279f1c579b1SScott Long 			xpt_done(pccb);
3280f1c579b1SScott Long 			break;
3281f1c579b1SScott Long 		}
3282ad6d6297SScott Long 	case XPT_GET_TRAN_SETTINGS: {
3283ad6d6297SScott Long 			struct ccb_trans_settings *cts;
3284ad6d6297SScott Long 
3285ad6d6297SScott Long 			if(pccb->ccb_h.target_id == 16) {
3286ad6d6297SScott Long 				pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL;
3287ad6d6297SScott Long 				xpt_done(pccb);
3288ad6d6297SScott Long 				break;
3289ad6d6297SScott Long 			}
3290ad6d6297SScott Long 			cts = &pccb->cts;
329144f05562SScott Long 			{
329244f05562SScott Long 				struct ccb_trans_settings_scsi *scsi;
329344f05562SScott Long 				struct ccb_trans_settings_spi *spi;
3294dac36688SXin LI 				struct ccb_trans_settings_sas *sas;
329544f05562SScott Long 
3296ad6d6297SScott Long 				scsi = &cts->proto_specific.scsi;
3297dac36688SXin LI 				scsi->flags = CTS_SCSI_FLAGS_TAG_ENB;
3298dac36688SXin LI 				scsi->valid = CTS_SCSI_VALID_TQ;
3299fa9ed865SMatt Jacob 				cts->protocol = PROTO_SCSI;
3300dac36688SXin LI 
3301dac36688SXin LI 				if((acb->vendor_device_id == PCIDevVenIDARC1880) ||
3302a1103e04SXin LI 				   (acb->vendor_device_id == PCIDevVenIDARC1884) ||
33037a7bc959SXin LI 				   (acb->vendor_device_id == PCIDevVenIDARC1680) ||
33047a7bc959SXin LI 				   (acb->vendor_device_id == PCIDevVenIDARC1214))
3305dac36688SXin LI 				{
3306dac36688SXin LI 					cts->protocol_version = SCSI_REV_SPC2;
3307dac36688SXin LI 					cts->transport_version = 0;
3308dac36688SXin LI 					cts->transport = XPORT_SAS;
3309dac36688SXin LI 					sas = &cts->xport_specific.sas;
3310dac36688SXin LI 					sas->valid = CTS_SAS_VALID_SPEED;
3311b23a1998SXin LI 					if (acb->adapter_bus_speed == ACB_BUS_SPEED_12G)
3312224a78aeSXin LI 						sas->bitrate = 1200000;
3313b23a1998SXin LI 					else if(acb->adapter_bus_speed == ACB_BUS_SPEED_6G)
3314dac36688SXin LI 						sas->bitrate = 600000;
3315b23a1998SXin LI 					else if(acb->adapter_bus_speed == ACB_BUS_SPEED_3G)
3316dac36688SXin LI 						sas->bitrate = 300000;
3317dac36688SXin LI 				}
3318dac36688SXin LI 				else
3319dac36688SXin LI 				{
3320fa9ed865SMatt Jacob 					cts->protocol_version = SCSI_REV_2;
3321fa9ed865SMatt Jacob 					cts->transport_version = 2;
3322dac36688SXin LI 					cts->transport = XPORT_SPI;
3323dac36688SXin LI 					spi = &cts->xport_specific.spi;
3324fa9ed865SMatt Jacob 					spi->flags = CTS_SPI_FLAGS_DISC_ENB;
3325b23a1998SXin LI 					if (acb->adapter_bus_speed == ACB_BUS_SPEED_6G)
3326b23a1998SXin LI 						spi->sync_period = 1;
3327b23a1998SXin LI 					else
3328dac36688SXin LI 						spi->sync_period = 2;
3329fa9ed865SMatt Jacob 					spi->sync_offset = 32;
3330fa9ed865SMatt Jacob 					spi->bus_width = MSG_EXT_WDTR_BUS_16_BIT;
33319d98ff4dSScott Long 					spi->valid = CTS_SPI_VALID_DISC
33329d98ff4dSScott Long 						| CTS_SPI_VALID_SYNC_RATE
3333fa9ed865SMatt Jacob 						| CTS_SPI_VALID_SYNC_OFFSET
3334fa9ed865SMatt Jacob 						| CTS_SPI_VALID_BUS_WIDTH;
3335dac36688SXin LI 				}
333644f05562SScott Long 			}
3337ad6d6297SScott Long 			pccb->ccb_h.status |= CAM_REQ_CMP;
3338ad6d6297SScott Long 			xpt_done(pccb);
3339ad6d6297SScott Long 			break;
3340ad6d6297SScott Long 		}
3341ad6d6297SScott Long 	case XPT_SET_TRAN_SETTINGS: {
3342ad6d6297SScott Long 			pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL;
3343ad6d6297SScott Long 			xpt_done(pccb);
3344ad6d6297SScott Long 			break;
3345ad6d6297SScott Long 		}
3346f3b080e6SMarius Strobl 	case XPT_CALC_GEOMETRY:
3347ad6d6297SScott Long 			if(pccb->ccb_h.target_id == 16) {
3348ad6d6297SScott Long 				pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL;
3349ad6d6297SScott Long 				xpt_done(pccb);
3350ad6d6297SScott Long 				break;
3351ad6d6297SScott Long 			}
3352f3b080e6SMarius Strobl 			cam_calc_geometry(&pccb->ccg, 1);
3353f1c579b1SScott Long 			xpt_done(pccb);
3354f1c579b1SScott Long 			break;
3355f1c579b1SScott Long 	default:
3356ad6d6297SScott Long 		pccb->ccb_h.status |= CAM_REQ_INVALID;
3357f1c579b1SScott Long 		xpt_done(pccb);
3358f1c579b1SScott Long 		break;
3359f1c579b1SScott Long 	}
3360f1c579b1SScott Long }
3361f1c579b1SScott Long /*
3362f1c579b1SScott Long **********************************************************************
3363f1c579b1SScott Long **********************************************************************
3364f1c579b1SScott Long */
336544f05562SScott Long static void arcmsr_start_hba_bgrb(struct AdapterControlBlock *acb)
3366f1c579b1SScott Long {
3367ad6d6297SScott Long 	acb->acb_flags |= ACB_F_MSG_START_BGRB;
336844f05562SScott Long 	CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB);
336944f05562SScott Long 	if(!arcmsr_hba_wait_msgint_ready(acb)) {
3370*2f7e72bdSMustafa Ateş Uzun 		printf("arcmsr%d: wait 'start adapter background rebuild' timeout \n", acb->pci_unit);
3371ad6d6297SScott Long 	}
3372f1c579b1SScott Long }
3373f1c579b1SScott Long /*
3374f1c579b1SScott Long **********************************************************************
3375f1c579b1SScott Long **********************************************************************
3376f1c579b1SScott Long */
337744f05562SScott Long static void arcmsr_start_hbb_bgrb(struct AdapterControlBlock *acb)
337844f05562SScott Long {
3379b23a1998SXin LI 	struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
338044f05562SScott Long 	acb->acb_flags |= ACB_F_MSG_START_BGRB;
3381b23a1998SXin LI 	WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_START_BGRB);
338244f05562SScott Long 	if(!arcmsr_hbb_wait_msgint_ready(acb)) {
3383*2f7e72bdSMustafa Ateş Uzun 		printf( "arcmsr%d: wait 'start adapter background rebuild' timeout \n", acb->pci_unit);
338444f05562SScott Long 	}
338544f05562SScott Long }
338644f05562SScott Long /*
338744f05562SScott Long **********************************************************************
338844f05562SScott Long **********************************************************************
338944f05562SScott Long */
3390d74001adSXin LI static void arcmsr_start_hbc_bgrb(struct AdapterControlBlock *acb)
3391d74001adSXin LI {
3392d74001adSXin LI 	acb->acb_flags |= ACB_F_MSG_START_BGRB;
3393d74001adSXin LI 	CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB);
3394d74001adSXin LI 	CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE);
3395d74001adSXin LI 	if(!arcmsr_hbc_wait_msgint_ready(acb)) {
3396*2f7e72bdSMustafa Ateş Uzun 		printf("arcmsr%d: wait 'start adapter background rebuild' timeout \n", acb->pci_unit);
3397d74001adSXin LI 	}
3398d74001adSXin LI }
3399d74001adSXin LI /*
3400d74001adSXin LI **********************************************************************
3401d74001adSXin LI **********************************************************************
3402d74001adSXin LI */
34037a7bc959SXin LI static void arcmsr_start_hbd_bgrb(struct AdapterControlBlock *acb)
34047a7bc959SXin LI {
34057a7bc959SXin LI 	acb->acb_flags |= ACB_F_MSG_START_BGRB;
34067a7bc959SXin LI 	CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB);
34077a7bc959SXin LI 	if(!arcmsr_hbd_wait_msgint_ready(acb)) {
3408*2f7e72bdSMustafa Ateş Uzun 		printf("arcmsr%d: wait 'start adapter background rebuild' timeout \n", acb->pci_unit);
34097a7bc959SXin LI 	}
34107a7bc959SXin LI }
34117a7bc959SXin LI /*
34127a7bc959SXin LI **********************************************************************
34137a7bc959SXin LI **********************************************************************
34147a7bc959SXin LI */
3415a1103e04SXin LI static void arcmsr_start_hbe_bgrb(struct AdapterControlBlock *acb)
3416a1103e04SXin LI {
3417a1103e04SXin LI 	acb->acb_flags |= ACB_F_MSG_START_BGRB;
3418a1103e04SXin LI 	CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB);
3419a1103e04SXin LI 	acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
3420a1103e04SXin LI 	CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
3421a1103e04SXin LI 	if(!arcmsr_hbe_wait_msgint_ready(acb)) {
3422*2f7e72bdSMustafa Ateş Uzun 		printf("arcmsr%d: wait 'start adapter background rebuild' timeout \n", acb->pci_unit);
3423a1103e04SXin LI 	}
3424a1103e04SXin LI }
3425a1103e04SXin LI /*
3426a1103e04SXin LI **********************************************************************
3427a1103e04SXin LI **********************************************************************
3428a1103e04SXin LI */
342944f05562SScott Long static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb)
343044f05562SScott Long {
343144f05562SScott Long 	switch (acb->adapter_type) {
343244f05562SScott Long 	case ACB_ADAPTER_TYPE_A:
343344f05562SScott Long 		arcmsr_start_hba_bgrb(acb);
343444f05562SScott Long 		break;
343544f05562SScott Long 	case ACB_ADAPTER_TYPE_B:
343644f05562SScott Long 		arcmsr_start_hbb_bgrb(acb);
343744f05562SScott Long 		break;
3438d74001adSXin LI 	case ACB_ADAPTER_TYPE_C:
3439d74001adSXin LI 		arcmsr_start_hbc_bgrb(acb);
3440d74001adSXin LI 		break;
34417a7bc959SXin LI 	case ACB_ADAPTER_TYPE_D:
34427a7bc959SXin LI 		arcmsr_start_hbd_bgrb(acb);
34437a7bc959SXin LI 		break;
3444a1103e04SXin LI 	case ACB_ADAPTER_TYPE_E:
3445fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_F:
3446a1103e04SXin LI 		arcmsr_start_hbe_bgrb(acb);
3447a1103e04SXin LI 		break;
344844f05562SScott Long 	}
344944f05562SScott Long }
345044f05562SScott Long /*
345144f05562SScott Long **********************************************************************
345244f05562SScott Long **
345344f05562SScott Long **********************************************************************
345444f05562SScott Long */
345544f05562SScott Long static void arcmsr_polling_hba_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb)
3456f1c579b1SScott Long {
3457ad6d6297SScott Long 	struct CommandControlBlock *srb;
345844f05562SScott Long 	u_int32_t flag_srb, outbound_intstatus, poll_srb_done=0, poll_count=0;
3459d74001adSXin LI 	u_int16_t	error;
3460f1c579b1SScott Long 
346144f05562SScott Long polling_ccb_retry:
3462ad6d6297SScott Long 	poll_count++;
3463d74001adSXin LI 	outbound_intstatus=CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & acb->outbound_int_enable;
3464d74001adSXin LI 	CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, outbound_intstatus);	/*clear interrupt*/
346544f05562SScott Long 	bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
3466ad6d6297SScott Long 	while(1) {
346744f05562SScott Long 		if((flag_srb = CHIP_REG_READ32(HBA_MessageUnit,
346844f05562SScott Long 			0, outbound_queueport)) == 0xFFFFFFFF) {
3469ad6d6297SScott Long 			if(poll_srb_done) {
3470ad6d6297SScott Long 				break;/*chip FIFO no ccb for completion already*/
3471ad6d6297SScott Long 			} else {
3472ad6d6297SScott Long 				UDELAY(25000);
3473d74001adSXin LI 				if ((poll_count > 100) && (poll_srb != NULL)) {
3474ad6d6297SScott Long 					break;
3475f1c579b1SScott Long 				}
347644f05562SScott Long 				goto polling_ccb_retry;
3477f1c579b1SScott Long 			}
3478ad6d6297SScott Long 		}
3479ad6d6297SScott Long 		/* check if command done with no error*/
348044f05562SScott Long 		srb = (struct CommandControlBlock *)
348144f05562SScott Long 			(acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/
3482d74001adSXin LI 		error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE;
348344f05562SScott Long 		poll_srb_done = (srb == poll_srb) ? 1:0;
348422f2616bSXin LI 		if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) {
348522f2616bSXin LI 			if(srb->srb_state == ARCMSR_SRB_ABORTED) {
3486123055f0SNathan Whitehorn 				printf("arcmsr%d: scsi id=%d lun=%jx srb='%p'"
3487ad6d6297SScott Long 					"poll command abort successfully \n"
3488ad6d6297SScott Long 					, acb->pci_unit
3489ad6d6297SScott Long 					, srb->pccb->ccb_h.target_id
3490123055f0SNathan Whitehorn 					, (uintmax_t)srb->pccb->ccb_h.target_lun, srb);
3491ad6d6297SScott Long 				srb->pccb->ccb_h.status |= CAM_REQ_ABORTED;
3492ad6d6297SScott Long 				arcmsr_srb_complete(srb, 1);
3493ad6d6297SScott Long 				continue;
3494ad6d6297SScott Long 			}
3495ad6d6297SScott Long 			printf("arcmsr%d: polling get an illegal srb command done srb='%p'"
3496ad6d6297SScott Long 				"srboutstandingcount=%d \n"
3497ad6d6297SScott Long 				, acb->pci_unit
3498ad6d6297SScott Long 				, srb, acb->srboutstandingcount);
3499ad6d6297SScott Long 			continue;
3500ad6d6297SScott Long 		}
3501d74001adSXin LI 		arcmsr_report_srb_state(acb, srb, error);
3502ad6d6297SScott Long 	}	/*drain reply FIFO*/
3503f1c579b1SScott Long }
3504f1c579b1SScott Long /*
3505f1c579b1SScott Long **********************************************************************
350644f05562SScott Long **
3507ad6d6297SScott Long **********************************************************************
3508ad6d6297SScott Long */
350944f05562SScott Long static void arcmsr_polling_hbb_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb)
351044f05562SScott Long {
351144f05562SScott Long 	struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
351244f05562SScott Long 	struct CommandControlBlock *srb;
351344f05562SScott Long 	u_int32_t flag_srb, poll_srb_done=0, poll_count=0;
351444f05562SScott Long 	int index;
3515d74001adSXin LI 	u_int16_t	error;
351644f05562SScott Long 
351744f05562SScott Long polling_ccb_retry:
351844f05562SScott Long 	poll_count++;
3519b23a1998SXin LI 	WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell, ARCMSR_DOORBELL_INT_CLEAR_PATTERN); /* clear doorbell interrupt */
352044f05562SScott Long 	bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
352144f05562SScott Long 	while(1) {
352244f05562SScott Long 		index = phbbmu->doneq_index;
352344f05562SScott Long 		if((flag_srb = phbbmu->done_qbuffer[index]) == 0) {
352444f05562SScott Long 			if(poll_srb_done) {
352544f05562SScott Long 				break;/*chip FIFO no ccb for completion already*/
352644f05562SScott Long 			} else {
352744f05562SScott Long 				UDELAY(25000);
3528d74001adSXin LI 				if ((poll_count > 100) && (poll_srb != NULL)) {
352944f05562SScott Long 					break;
353044f05562SScott Long 				}
353144f05562SScott Long 				goto polling_ccb_retry;
353244f05562SScott Long 			}
353344f05562SScott Long 		}
353444f05562SScott Long 		phbbmu->done_qbuffer[index] = 0;
353544f05562SScott Long 		index++;
353644f05562SScott Long 		index %= ARCMSR_MAX_HBB_POSTQUEUE;     /*if last index number set it to 0 */
353744f05562SScott Long 		phbbmu->doneq_index = index;
353844f05562SScott Long 		/* check if command done with no error*/
353944f05562SScott Long 		srb = (struct CommandControlBlock *)
354044f05562SScott Long 			(acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/
3541d74001adSXin LI 		error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE;
354244f05562SScott Long 		poll_srb_done = (srb == poll_srb) ? 1:0;
354322f2616bSXin LI 		if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) {
354422f2616bSXin LI 			if(srb->srb_state == ARCMSR_SRB_ABORTED) {
3545123055f0SNathan Whitehorn 				printf("arcmsr%d: scsi id=%d lun=%jx srb='%p'"
354644f05562SScott Long 					"poll command abort successfully \n"
354744f05562SScott Long 					, acb->pci_unit
354844f05562SScott Long 					, srb->pccb->ccb_h.target_id
3549123055f0SNathan Whitehorn 					, (uintmax_t)srb->pccb->ccb_h.target_lun, srb);
355044f05562SScott Long 				srb->pccb->ccb_h.status |= CAM_REQ_ABORTED;
355144f05562SScott Long 				arcmsr_srb_complete(srb, 1);
355244f05562SScott Long 				continue;
355344f05562SScott Long 			}
355444f05562SScott Long 			printf("arcmsr%d: polling get an illegal srb command done srb='%p'"
355544f05562SScott Long 				"srboutstandingcount=%d \n"
355644f05562SScott Long 				, acb->pci_unit
355744f05562SScott Long 				, srb, acb->srboutstandingcount);
355844f05562SScott Long 			continue;
355944f05562SScott Long 		}
3560d74001adSXin LI 		arcmsr_report_srb_state(acb, srb, error);
3561d74001adSXin LI 	}	/*drain reply FIFO*/
3562d74001adSXin LI }
3563d74001adSXin LI /*
3564d74001adSXin LI **********************************************************************
3565d74001adSXin LI **
3566d74001adSXin LI **********************************************************************
3567d74001adSXin LI */
3568d74001adSXin LI static void arcmsr_polling_hbc_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb)
3569d74001adSXin LI {
3570d74001adSXin LI 	struct CommandControlBlock *srb;
3571d74001adSXin LI 	u_int32_t flag_srb, poll_srb_done=0, poll_count=0;
3572d74001adSXin LI 	u_int16_t	error;
3573d74001adSXin LI 
3574d74001adSXin LI polling_ccb_retry:
3575d74001adSXin LI 	poll_count++;
3576d74001adSXin LI 	bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
3577d74001adSXin LI 	while(1) {
3578d74001adSXin LI 		if(!(CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR)) {
3579d74001adSXin LI 			if(poll_srb_done) {
3580d74001adSXin LI 				break;/*chip FIFO no ccb for completion already*/
3581d74001adSXin LI 			} else {
3582d74001adSXin LI 				UDELAY(25000);
3583d74001adSXin LI 				if ((poll_count > 100) && (poll_srb != NULL)) {
3584d74001adSXin LI 					break;
3585d74001adSXin LI 				}
3586d74001adSXin LI 				if (acb->srboutstandingcount == 0) {
3587d74001adSXin LI 					break;
3588d74001adSXin LI 				}
3589d74001adSXin LI 				goto polling_ccb_retry;
3590d74001adSXin LI 			}
3591d74001adSXin LI 		}
3592d74001adSXin LI 		flag_srb = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_queueport_low);
3593d74001adSXin LI 		/* check if command done with no error*/
359422f2616bSXin LI 		srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb & 0xFFFFFFE0));/*frame must be 32 bytes aligned*/
3595d74001adSXin LI 		error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1)?TRUE:FALSE;
3596d74001adSXin LI 		if (poll_srb != NULL)
3597d74001adSXin LI 			poll_srb_done = (srb == poll_srb) ? 1:0;
359822f2616bSXin LI 		if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) {
359922f2616bSXin LI 			if(srb->srb_state == ARCMSR_SRB_ABORTED) {
3600123055f0SNathan Whitehorn 				printf("arcmsr%d: scsi id=%d lun=%jx srb='%p'poll command abort successfully \n"
3601123055f0SNathan Whitehorn 						, acb->pci_unit, srb->pccb->ccb_h.target_id, (uintmax_t)srb->pccb->ccb_h.target_lun, srb);
3602d74001adSXin LI 				srb->pccb->ccb_h.status |= CAM_REQ_ABORTED;
3603d74001adSXin LI 				arcmsr_srb_complete(srb, 1);
3604d74001adSXin LI 				continue;
3605d74001adSXin LI 			}
3606d74001adSXin LI 			printf("arcmsr%d: polling get an illegal srb command done srb='%p'srboutstandingcount=%d \n"
3607d74001adSXin LI 					, acb->pci_unit, srb, acb->srboutstandingcount);
3608d74001adSXin LI 			continue;
3609d74001adSXin LI 		}
3610d74001adSXin LI 		arcmsr_report_srb_state(acb, srb, error);
361144f05562SScott Long 	}	/*drain reply FIFO*/
361244f05562SScott Long }
361344f05562SScott Long /*
361444f05562SScott Long **********************************************************************
36157a7bc959SXin LI **
36167a7bc959SXin LI **********************************************************************
36177a7bc959SXin LI */
36187a7bc959SXin LI static void arcmsr_polling_hbd_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb)
36197a7bc959SXin LI {
36207a7bc959SXin LI 	struct HBD_MessageUnit0 *phbdmu = (struct HBD_MessageUnit0 *)acb->pmu;
36217a7bc959SXin LI 	struct CommandControlBlock *srb;
36227a7bc959SXin LI 	u_int32_t flag_srb, poll_srb_done=0, poll_count=0;
36237a7bc959SXin LI 	u_int32_t outbound_write_pointer;
36247a7bc959SXin LI 	u_int16_t	error, doneq_index;
36257a7bc959SXin LI 
36267a7bc959SXin LI polling_ccb_retry:
36277a7bc959SXin LI 	poll_count++;
36287a7bc959SXin LI 	bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
36297a7bc959SXin LI 	while(1) {
36307a7bc959SXin LI 		outbound_write_pointer = phbdmu->done_qbuffer[0].addressLow;
36317a7bc959SXin LI 		doneq_index = phbdmu->doneq_index;
36327a7bc959SXin LI 		if ((outbound_write_pointer & 0xFF) == (doneq_index & 0xFF)) {
36337a7bc959SXin LI 			if(poll_srb_done) {
36347a7bc959SXin LI 				break;/*chip FIFO no ccb for completion already*/
36357a7bc959SXin LI 			} else {
36367a7bc959SXin LI 				UDELAY(25000);
36377a7bc959SXin LI 				if ((poll_count > 100) && (poll_srb != NULL)) {
36387a7bc959SXin LI 					break;
36397a7bc959SXin LI 				}
36407a7bc959SXin LI 				if (acb->srboutstandingcount == 0) {
36417a7bc959SXin LI 					break;
36427a7bc959SXin LI 				}
36437a7bc959SXin LI 				goto polling_ccb_retry;
36447a7bc959SXin LI 			}
36457a7bc959SXin LI 		}
36467a7bc959SXin LI 		doneq_index = arcmsr_get_doneq_index(phbdmu);
36477a7bc959SXin LI 		flag_srb = phbdmu->done_qbuffer[(doneq_index & 0xFF)+1].addressLow;
36487a7bc959SXin LI 		/* check if command done with no error*/
36497a7bc959SXin LI 		srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb & 0xFFFFFFE0));/*frame must be 32 bytes aligned*/
36507a7bc959SXin LI 		error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE;
36517a7bc959SXin LI 		CHIP_REG_WRITE32(HBD_MessageUnit, 0, outboundlist_read_pointer, doneq_index);
36527a7bc959SXin LI 		if (poll_srb != NULL)
36537a7bc959SXin LI 			poll_srb_done = (srb == poll_srb) ? 1:0;
36547a7bc959SXin LI 		if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) {
36557a7bc959SXin LI 			if(srb->srb_state == ARCMSR_SRB_ABORTED) {
3656123055f0SNathan Whitehorn 				printf("arcmsr%d: scsi id=%d lun=%jx srb='%p'poll command abort successfully \n"
3657123055f0SNathan Whitehorn 						, acb->pci_unit, srb->pccb->ccb_h.target_id, (uintmax_t)srb->pccb->ccb_h.target_lun, srb);
36587a7bc959SXin LI 				srb->pccb->ccb_h.status |= CAM_REQ_ABORTED;
36597a7bc959SXin LI 				arcmsr_srb_complete(srb, 1);
36607a7bc959SXin LI 				continue;
36617a7bc959SXin LI 			}
36627a7bc959SXin LI 			printf("arcmsr%d: polling get an illegal srb command done srb='%p'srboutstandingcount=%d \n"
36637a7bc959SXin LI 					, acb->pci_unit, srb, acb->srboutstandingcount);
36647a7bc959SXin LI 			continue;
36657a7bc959SXin LI 		}
36667a7bc959SXin LI 		arcmsr_report_srb_state(acb, srb, error);
36677a7bc959SXin LI 	}	/*drain reply FIFO*/
36687a7bc959SXin LI }
36697a7bc959SXin LI /*
36707a7bc959SXin LI **********************************************************************
3671a1103e04SXin LI **
3672a1103e04SXin LI **********************************************************************
3673a1103e04SXin LI */
3674a1103e04SXin LI static void arcmsr_polling_hbe_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb)
3675a1103e04SXin LI {
3676a1103e04SXin LI 	struct CommandControlBlock *srb;
3677a1103e04SXin LI 	u_int32_t poll_srb_done=0, poll_count=0, doneq_index;
3678a1103e04SXin LI 	u_int16_t	error, cmdSMID;
3679a1103e04SXin LI 
3680a1103e04SXin LI polling_ccb_retry:
3681a1103e04SXin LI 	poll_count++;
3682a1103e04SXin LI 	bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
3683a1103e04SXin LI 	while(1) {
3684a1103e04SXin LI 		doneq_index = acb->doneq_index;
3685a1103e04SXin LI 		if((CHIP_REG_READ32(HBE_MessageUnit, 0, reply_post_producer_index) & 0xFFFF) == doneq_index) {
3686a1103e04SXin LI 			if(poll_srb_done) {
3687a1103e04SXin LI 				break;/*chip FIFO no ccb for completion already*/
3688a1103e04SXin LI 			} else {
3689a1103e04SXin LI 				UDELAY(25000);
3690a1103e04SXin LI 				if ((poll_count > 100) && (poll_srb != NULL)) {
3691a1103e04SXin LI 					break;
3692a1103e04SXin LI 				}
3693a1103e04SXin LI 				if (acb->srboutstandingcount == 0) {
3694a1103e04SXin LI 					break;
3695a1103e04SXin LI 				}
3696a1103e04SXin LI 				goto polling_ccb_retry;
3697a1103e04SXin LI 			}
3698a1103e04SXin LI 		}
3699a1103e04SXin LI 		cmdSMID = acb->pCompletionQ[doneq_index].cmdSMID;
3700a1103e04SXin LI 		doneq_index++;
3701a1103e04SXin LI 		if (doneq_index >= acb->completionQ_entry)
3702a1103e04SXin LI 			doneq_index = 0;
3703a1103e04SXin LI 		acb->doneq_index = doneq_index;
3704a1103e04SXin LI 		srb = acb->psrb_pool[cmdSMID];
3705a1103e04SXin LI 		error = (acb->pCompletionQ[doneq_index].cmdFlag & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE;
3706a1103e04SXin LI 		if (poll_srb != NULL)
3707a1103e04SXin LI 			poll_srb_done = (srb == poll_srb) ? 1:0;
3708a1103e04SXin LI 		if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) {
3709a1103e04SXin LI 			if(srb->srb_state == ARCMSR_SRB_ABORTED) {
3710a1103e04SXin LI 				printf("arcmsr%d: scsi id=%d lun=%jx srb='%p'poll command abort successfully \n"
3711a1103e04SXin LI 						, acb->pci_unit, srb->pccb->ccb_h.target_id, (uintmax_t)srb->pccb->ccb_h.target_lun, srb);
3712a1103e04SXin LI 				srb->pccb->ccb_h.status |= CAM_REQ_ABORTED;
3713a1103e04SXin LI 				arcmsr_srb_complete(srb, 1);
3714a1103e04SXin LI 				continue;
3715a1103e04SXin LI 			}
3716a1103e04SXin LI 			printf("arcmsr%d: polling get an illegal srb command done srb='%p'srboutstandingcount=%d \n"
3717a1103e04SXin LI 					, acb->pci_unit, srb, acb->srboutstandingcount);
3718a1103e04SXin LI 			continue;
3719a1103e04SXin LI 		}
3720a1103e04SXin LI 		arcmsr_report_srb_state(acb, srb, error);
3721a1103e04SXin LI 	}	/*drain reply FIFO*/
3722a1103e04SXin LI 	CHIP_REG_WRITE32(HBE_MessageUnit, 0, reply_post_producer_index, doneq_index);
3723a1103e04SXin LI }
3724a1103e04SXin LI /*
3725a1103e04SXin LI **********************************************************************
372644f05562SScott Long **********************************************************************
372744f05562SScott Long */
372844f05562SScott Long static void arcmsr_polling_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb)
372944f05562SScott Long {
373044f05562SScott Long 	switch (acb->adapter_type) {
3731fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_A:
373244f05562SScott Long 		arcmsr_polling_hba_srbdone(acb, poll_srb);
373344f05562SScott Long 		break;
3734fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_B:
373544f05562SScott Long 		arcmsr_polling_hbb_srbdone(acb, poll_srb);
373644f05562SScott Long 		break;
3737fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_C:
3738d74001adSXin LI 		arcmsr_polling_hbc_srbdone(acb, poll_srb);
3739d74001adSXin LI 		break;
3740fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_D:
37417a7bc959SXin LI 		arcmsr_polling_hbd_srbdone(acb, poll_srb);
37427a7bc959SXin LI 		break;
3743fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_E:
3744fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_F:
3745a1103e04SXin LI 		arcmsr_polling_hbe_srbdone(acb, poll_srb);
3746a1103e04SXin LI 		break;
374744f05562SScott Long 	}
374844f05562SScott Long }
374944f05562SScott Long /*
375044f05562SScott Long **********************************************************************
375144f05562SScott Long **********************************************************************
375244f05562SScott Long */
375344f05562SScott Long static void arcmsr_get_hba_config(struct AdapterControlBlock *acb)
3754ad6d6297SScott Long {
3755ad6d6297SScott Long 	char *acb_firm_model = acb->firm_model;
3756ad6d6297SScott Long 	char *acb_firm_version = acb->firm_version;
3757d74001adSXin LI 	char *acb_device_map = acb->device_map;
3758d74001adSXin LI 	size_t iop_firm_model = offsetof(struct HBA_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]);	/*firm_model,15,60-67*/
3759d74001adSXin LI 	size_t iop_firm_version = offsetof(struct HBA_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]);	/*firm_version,17,68-83*/
3760d74001adSXin LI 	size_t iop_device_map = offsetof(struct HBA_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
3761ad6d6297SScott Long 	int i;
3762ad6d6297SScott Long 
376344f05562SScott Long 	CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG);
376444f05562SScott Long 	if(!arcmsr_hba_wait_msgint_ready(acb)) {
3765d74001adSXin LI 		printf("arcmsr%d: wait 'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit);
3766ad6d6297SScott Long 	}
3767ad6d6297SScott Long 	i = 0;
3768ad6d6297SScott Long 	while(i < 8) {
376944f05562SScott Long 		*acb_firm_model = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_model+i);
3770ad6d6297SScott Long 		/* 8 bytes firm_model, 15, 60-67*/
3771ad6d6297SScott Long 		acb_firm_model++;
3772ad6d6297SScott Long 		i++;
3773ad6d6297SScott Long 	}
3774ad6d6297SScott Long 	i=0;
3775ad6d6297SScott Long 	while(i < 16) {
377644f05562SScott Long 		*acb_firm_version = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_version+i);
3777ad6d6297SScott Long 		/* 16 bytes firm_version, 17, 68-83*/
3778ad6d6297SScott Long 		acb_firm_version++;
3779ad6d6297SScott Long 		i++;
3780ad6d6297SScott Long 	}
3781d74001adSXin LI 	i=0;
3782d74001adSXin LI 	while(i < 16) {
3783d74001adSXin LI 		*acb_device_map = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_device_map+i);
3784d74001adSXin LI 		acb_device_map++;
3785d74001adSXin LI 		i++;
3786d74001adSXin LI 	}
37871e7d660aSXin LI 	printf("Areca RAID adapter%d: %s F/W version %s \n", acb->pci_unit, acb->firm_model, acb->firm_version);
3788d74001adSXin LI 	acb->firm_request_len = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[1]);   /*firm_request_len, 1, 04-07*/
3789d74001adSXin LI 	acb->firm_numbers_queue = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/
3790d74001adSXin LI 	acb->firm_sdram_size = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[3]);    /*firm_sdram_size, 3, 12-15*/
3791d74001adSXin LI 	acb->firm_ide_channels = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[4]);  /*firm_ide_channels, 4, 16-19*/
3792d74001adSXin LI 	acb->firm_cfg_version = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]);	/*firm_cfg_version,  25, 	  */
3793abfdbca9SXin LI 	if(acb->firm_numbers_queue > ARCMSR_MAX_OUTSTANDING_CMD)
3794abfdbca9SXin LI 		acb->maxOutstanding = ARCMSR_MAX_OUTSTANDING_CMD - 1;
3795abfdbca9SXin LI 	else
3796abfdbca9SXin LI 		acb->maxOutstanding = acb->firm_numbers_queue - 1;
3797ad6d6297SScott Long }
3798ad6d6297SScott Long /*
3799ad6d6297SScott Long **********************************************************************
380044f05562SScott Long **********************************************************************
380144f05562SScott Long */
380244f05562SScott Long static void arcmsr_get_hbb_config(struct AdapterControlBlock *acb)
380344f05562SScott Long {
3804b23a1998SXin LI 	struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
380544f05562SScott Long 	char *acb_firm_model = acb->firm_model;
380644f05562SScott Long 	char *acb_firm_version = acb->firm_version;
3807d74001adSXin LI 	char *acb_device_map = acb->device_map;
3808d74001adSXin LI 	size_t iop_firm_model = offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]);	/*firm_model,15,60-67*/
3809d74001adSXin LI 	size_t iop_firm_version = offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]);	/*firm_version,17,68-83*/
3810d74001adSXin LI 	size_t iop_device_map = offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
381144f05562SScott Long 	int i;
381244f05562SScott Long 
3813b23a1998SXin LI 	WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_GET_CONFIG);
381444f05562SScott Long 	if(!arcmsr_hbb_wait_msgint_ready(acb)) {
3815d74001adSXin LI 		printf( "arcmsr%d: wait" "'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit);
381644f05562SScott Long 	}
381744f05562SScott Long 	i = 0;
381844f05562SScott Long 	while(i < 8) {
381944f05562SScott Long 		*acb_firm_model = bus_space_read_1(acb->btag[1], acb->bhandle[1], iop_firm_model+i);
382044f05562SScott Long 		/* 8 bytes firm_model, 15, 60-67*/
382144f05562SScott Long 		acb_firm_model++;
382244f05562SScott Long 		i++;
382344f05562SScott Long 	}
382444f05562SScott Long 	i = 0;
382544f05562SScott Long 	while(i < 16) {
382644f05562SScott Long 		*acb_firm_version = bus_space_read_1(acb->btag[1], acb->bhandle[1], iop_firm_version+i);
382744f05562SScott Long 		/* 16 bytes firm_version, 17, 68-83*/
382844f05562SScott Long 		acb_firm_version++;
382944f05562SScott Long 		i++;
383044f05562SScott Long 	}
3831d74001adSXin LI 	i = 0;
3832d74001adSXin LI 	while(i < 16) {
3833d74001adSXin LI 		*acb_device_map = bus_space_read_1(acb->btag[1], acb->bhandle[1], iop_device_map+i);
3834d74001adSXin LI 		acb_device_map++;
3835d74001adSXin LI 		i++;
3836d74001adSXin LI 	}
38371e7d660aSXin LI 	printf("Areca RAID adapter%d: %s F/W version %s \n", acb->pci_unit, acb->firm_model, acb->firm_version);
3838d74001adSXin LI 	acb->firm_request_len = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[1]);   /*firm_request_len, 1, 04-07*/
3839d74001adSXin LI 	acb->firm_numbers_queue = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/
3840d74001adSXin LI 	acb->firm_sdram_size = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[3]);    /*firm_sdram_size, 3, 12-15*/
3841d74001adSXin LI 	acb->firm_ide_channels = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[4]);  /*firm_ide_channels, 4, 16-19*/
3842d74001adSXin LI 	acb->firm_cfg_version = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]);	/*firm_cfg_version,  25, 	  */
3843abfdbca9SXin LI 	if(acb->firm_numbers_queue > ARCMSR_MAX_HBB_POSTQUEUE)
3844abfdbca9SXin LI 		acb->maxOutstanding = ARCMSR_MAX_HBB_POSTQUEUE - 1;
3845abfdbca9SXin LI 	else
3846abfdbca9SXin LI 		acb->maxOutstanding = acb->firm_numbers_queue - 1;
3847d74001adSXin LI }
3848d74001adSXin LI /*
3849d74001adSXin LI **********************************************************************
3850d74001adSXin LI **********************************************************************
3851d74001adSXin LI */
3852d74001adSXin LI static void arcmsr_get_hbc_config(struct AdapterControlBlock *acb)
3853d74001adSXin LI {
3854d74001adSXin LI 	char *acb_firm_model = acb->firm_model;
3855d74001adSXin LI 	char *acb_firm_version = acb->firm_version;
3856d74001adSXin LI 	char *acb_device_map = acb->device_map;
3857d74001adSXin LI 	size_t iop_firm_model = offsetof(struct HBC_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]);   /*firm_model,15,60-67*/
3858d74001adSXin LI 	size_t iop_firm_version = offsetof(struct HBC_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/
3859d74001adSXin LI 	size_t iop_device_map = offsetof(struct HBC_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
3860d74001adSXin LI 	int i;
3861d74001adSXin LI 
3862d74001adSXin LI 	CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG);
3863d74001adSXin LI 	CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE);
3864d74001adSXin LI 	if(!arcmsr_hbc_wait_msgint_ready(acb)) {
3865d74001adSXin LI 		printf("arcmsr%d: wait 'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit);
3866d74001adSXin LI 	}
3867d74001adSXin LI 	i = 0;
3868d74001adSXin LI 	while(i < 8) {
3869d74001adSXin LI 		*acb_firm_model = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_model+i);
3870d74001adSXin LI 		/* 8 bytes firm_model, 15, 60-67*/
3871d74001adSXin LI 		acb_firm_model++;
3872d74001adSXin LI 		i++;
3873d74001adSXin LI 	}
3874d74001adSXin LI 	i = 0;
3875d74001adSXin LI 	while(i < 16) {
3876d74001adSXin LI 		*acb_firm_version = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_version+i);
3877d74001adSXin LI 		/* 16 bytes firm_version, 17, 68-83*/
3878d74001adSXin LI 		acb_firm_version++;
3879d74001adSXin LI 		i++;
3880d74001adSXin LI 	}
3881d74001adSXin LI 	i = 0;
3882d74001adSXin LI 	while(i < 16) {
3883d74001adSXin LI 		*acb_device_map = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_device_map+i);
3884d74001adSXin LI 		acb_device_map++;
3885d74001adSXin LI 		i++;
3886d74001adSXin LI 	}
38871e7d660aSXin LI 	printf("Areca RAID adapter%d: %s F/W version %s \n", acb->pci_unit, acb->firm_model, acb->firm_version);
3888d74001adSXin LI 	acb->firm_request_len	= CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[1]);	/*firm_request_len,   1, 04-07*/
3889d74001adSXin LI 	acb->firm_numbers_queue	= CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[2]);	/*firm_numbers_queue, 2, 08-11*/
3890d74001adSXin LI 	acb->firm_sdram_size	= CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[3]);	/*firm_sdram_size,    3, 12-15*/
3891d74001adSXin LI 	acb->firm_ide_channels	= CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[4]);	/*firm_ide_channels,  4, 16-19*/
3892d74001adSXin LI 	acb->firm_cfg_version	= CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]);	/*firm_cfg_version,  25, 	  */
3893abfdbca9SXin LI 	if(acb->firm_numbers_queue > ARCMSR_MAX_OUTSTANDING_CMD)
3894abfdbca9SXin LI 		acb->maxOutstanding = ARCMSR_MAX_OUTSTANDING_CMD - 1;
3895abfdbca9SXin LI 	else
3896abfdbca9SXin LI 		acb->maxOutstanding = acb->firm_numbers_queue - 1;
389744f05562SScott Long }
389844f05562SScott Long /*
389944f05562SScott Long **********************************************************************
390044f05562SScott Long **********************************************************************
390144f05562SScott Long */
39027a7bc959SXin LI static void arcmsr_get_hbd_config(struct AdapterControlBlock *acb)
39037a7bc959SXin LI {
39047a7bc959SXin LI 	char *acb_firm_model = acb->firm_model;
39057a7bc959SXin LI 	char *acb_firm_version = acb->firm_version;
39067a7bc959SXin LI 	char *acb_device_map = acb->device_map;
39077a7bc959SXin LI 	size_t iop_firm_model = offsetof(struct HBD_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]);   /*firm_model,15,60-67*/
39087a7bc959SXin LI 	size_t iop_firm_version = offsetof(struct HBD_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/
39097a7bc959SXin LI 	size_t iop_device_map = offsetof(struct HBD_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
39107a7bc959SXin LI 	int i;
39117a7bc959SXin LI 
39127a7bc959SXin LI 	if(CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE)
39137a7bc959SXin LI 		CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE_CLEAR);
39147a7bc959SXin LI 	CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG);
39157a7bc959SXin LI 	if(!arcmsr_hbd_wait_msgint_ready(acb)) {
39167a7bc959SXin LI 		printf("arcmsr%d: wait 'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit);
39177a7bc959SXin LI 	}
39187a7bc959SXin LI 	i = 0;
39197a7bc959SXin LI 	while(i < 8) {
39207a7bc959SXin LI 		*acb_firm_model = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_model+i);
39217a7bc959SXin LI 		/* 8 bytes firm_model, 15, 60-67*/
39227a7bc959SXin LI 		acb_firm_model++;
39237a7bc959SXin LI 		i++;
39247a7bc959SXin LI 	}
39257a7bc959SXin LI 	i = 0;
39267a7bc959SXin LI 	while(i < 16) {
39277a7bc959SXin LI 		*acb_firm_version = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_version+i);
39287a7bc959SXin LI 		/* 16 bytes firm_version, 17, 68-83*/
39297a7bc959SXin LI 		acb_firm_version++;
39307a7bc959SXin LI 		i++;
39317a7bc959SXin LI 	}
39327a7bc959SXin LI 	i = 0;
39337a7bc959SXin LI 	while(i < 16) {
39347a7bc959SXin LI 		*acb_device_map = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_device_map+i);
39357a7bc959SXin LI 		acb_device_map++;
39367a7bc959SXin LI 		i++;
39377a7bc959SXin LI 	}
39381e7d660aSXin LI 	printf("Areca RAID adapter%d: %s F/W version %s \n", acb->pci_unit, acb->firm_model, acb->firm_version);
3939b23a1998SXin LI 	acb->firm_request_len	= CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[1]);	/*firm_request_len,   1, 04-07*/
3940b23a1998SXin LI 	acb->firm_numbers_queue	= CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[2]);	/*firm_numbers_queue, 2, 08-11*/
3941b23a1998SXin LI 	acb->firm_sdram_size	= CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[3]);	/*firm_sdram_size,    3, 12-15*/
3942b23a1998SXin LI 	acb->firm_ide_channels	= CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[4]);	/*firm_ide_channels,  4, 16-19*/
39437a7bc959SXin LI 	acb->firm_cfg_version	= CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]);	/*firm_cfg_version,  25, 	  */
3944abfdbca9SXin LI 	if(acb->firm_numbers_queue > ARCMSR_MAX_HBD_POSTQUEUE)
3945abfdbca9SXin LI 		acb->maxOutstanding = ARCMSR_MAX_HBD_POSTQUEUE - 1;
3946abfdbca9SXin LI 	else
3947abfdbca9SXin LI 		acb->maxOutstanding = acb->firm_numbers_queue - 1;
39487a7bc959SXin LI }
39497a7bc959SXin LI /*
39507a7bc959SXin LI **********************************************************************
39517a7bc959SXin LI **********************************************************************
39527a7bc959SXin LI */
3953a1103e04SXin LI static void arcmsr_get_hbe_config(struct AdapterControlBlock *acb)
3954a1103e04SXin LI {
3955a1103e04SXin LI 	char *acb_firm_model = acb->firm_model;
3956a1103e04SXin LI 	char *acb_firm_version = acb->firm_version;
3957a1103e04SXin LI 	char *acb_device_map = acb->device_map;
3958a1103e04SXin LI 	size_t iop_firm_model = offsetof(struct HBE_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]);   /*firm_model,15,60-67*/
3959a1103e04SXin LI 	size_t iop_firm_version = offsetof(struct HBE_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/
3960a1103e04SXin LI 	size_t iop_device_map = offsetof(struct HBE_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
3961a1103e04SXin LI 	int i;
3962a1103e04SXin LI 
3963a1103e04SXin LI 	CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG);
3964a1103e04SXin LI 	acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
3965a1103e04SXin LI 	CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
3966a1103e04SXin LI 	if(!arcmsr_hbe_wait_msgint_ready(acb)) {
3967a1103e04SXin LI 		printf("arcmsr%d: wait 'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit);
3968a1103e04SXin LI 	}
3969a1103e04SXin LI 
3970a1103e04SXin LI 	i = 0;
3971a1103e04SXin LI 	while(i < 8) {
3972a1103e04SXin LI 		*acb_firm_model = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_model+i);
3973a1103e04SXin LI 		/* 8 bytes firm_model, 15, 60-67*/
3974a1103e04SXin LI 		acb_firm_model++;
3975a1103e04SXin LI 		i++;
3976a1103e04SXin LI 	}
3977a1103e04SXin LI 	i = 0;
3978a1103e04SXin LI 	while(i < 16) {
3979a1103e04SXin LI 		*acb_firm_version = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_version+i);
3980a1103e04SXin LI 		/* 16 bytes firm_version, 17, 68-83*/
3981a1103e04SXin LI 		acb_firm_version++;
3982a1103e04SXin LI 		i++;
3983a1103e04SXin LI 	}
3984a1103e04SXin LI 	i = 0;
3985a1103e04SXin LI 	while(i < 16) {
3986a1103e04SXin LI 		*acb_device_map = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_device_map+i);
3987a1103e04SXin LI 		acb_device_map++;
3988a1103e04SXin LI 		i++;
3989a1103e04SXin LI 	}
3990a1103e04SXin LI 	printf("Areca RAID adapter%d: %s F/W version %s \n", acb->pci_unit, acb->firm_model, acb->firm_version);
3991a1103e04SXin LI 	acb->firm_request_len	= CHIP_REG_READ32(HBE_MessageUnit, 0, msgcode_rwbuffer[1]);	/*firm_request_len,   1, 04-07*/
3992a1103e04SXin LI 	acb->firm_numbers_queue	= CHIP_REG_READ32(HBE_MessageUnit, 0, msgcode_rwbuffer[2]);	/*firm_numbers_queue, 2, 08-11*/
3993a1103e04SXin LI 	acb->firm_sdram_size	= CHIP_REG_READ32(HBE_MessageUnit, 0, msgcode_rwbuffer[3]);	/*firm_sdram_size,    3, 12-15*/
3994a1103e04SXin LI 	acb->firm_ide_channels	= CHIP_REG_READ32(HBE_MessageUnit, 0, msgcode_rwbuffer[4]);	/*firm_ide_channels,  4, 16-19*/
3995a1103e04SXin LI 	acb->firm_cfg_version	= CHIP_REG_READ32(HBE_MessageUnit, 0, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]);	/*firm_cfg_version,  25, 	  */
3996a1103e04SXin LI 	if(acb->firm_numbers_queue > ARCMSR_MAX_OUTSTANDING_CMD)
3997a1103e04SXin LI 		acb->maxOutstanding = ARCMSR_MAX_OUTSTANDING_CMD - 1;
3998a1103e04SXin LI 	else
3999a1103e04SXin LI 		acb->maxOutstanding = acb->firm_numbers_queue - 1;
4000a1103e04SXin LI }
4001a1103e04SXin LI /*
4002a1103e04SXin LI **********************************************************************
4003a1103e04SXin LI **********************************************************************
4004a1103e04SXin LI */
4005fa42a0bfSXin LI static void arcmsr_get_hbf_config(struct AdapterControlBlock *acb)
4006fa42a0bfSXin LI {
4007fa42a0bfSXin LI 	u_int32_t *acb_firm_model = (u_int32_t *)acb->firm_model;
4008fa42a0bfSXin LI 	u_int32_t *acb_firm_version = (u_int32_t *)acb->firm_version;
4009fa42a0bfSXin LI 	u_int32_t *acb_device_map = (u_int32_t *)acb->device_map;
4010fa42a0bfSXin LI 	size_t iop_firm_model = ARCMSR_FW_MODEL_OFFSET;   /*firm_model,15,60-67*/
4011fa42a0bfSXin LI 	size_t iop_firm_version = ARCMSR_FW_VERS_OFFSET; /*firm_version,17,68-83*/
4012fa42a0bfSXin LI 	size_t iop_device_map = ARCMSR_FW_DEVMAP_OFFSET;
4013fa42a0bfSXin LI 	int i;
4014fa42a0bfSXin LI 
4015fa42a0bfSXin LI 	CHIP_REG_WRITE32(HBF_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG);
4016fa42a0bfSXin LI 	acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
4017fa42a0bfSXin LI 	CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
4018fa42a0bfSXin LI 	if(!arcmsr_hbe_wait_msgint_ready(acb))
4019fa42a0bfSXin LI 		printf("arcmsr%d: wait 'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit);
4020fa42a0bfSXin LI 
4021fa42a0bfSXin LI 	i = 0;
4022fa42a0bfSXin LI 	while(i < 2) {
4023fa42a0bfSXin LI 		*acb_firm_model = acb->msgcode_rwbuffer[iop_firm_model];
4024fa42a0bfSXin LI 		/* 8 bytes firm_model, 15, 60-67*/
4025fa42a0bfSXin LI 		acb_firm_model++;
4026fa42a0bfSXin LI 		iop_firm_model++;
4027fa42a0bfSXin LI 		i++;
4028fa42a0bfSXin LI 	}
4029fa42a0bfSXin LI 	i = 0;
4030fa42a0bfSXin LI 	while(i < 4) {
4031fa42a0bfSXin LI 		*acb_firm_version = acb->msgcode_rwbuffer[iop_firm_version];
4032fa42a0bfSXin LI 		/* 16 bytes firm_version, 17, 68-83*/
4033fa42a0bfSXin LI 		acb_firm_version++;
4034fa42a0bfSXin LI 		iop_firm_version++;
4035fa42a0bfSXin LI 		i++;
4036fa42a0bfSXin LI 	}
4037fa42a0bfSXin LI 	i = 0;
4038fa42a0bfSXin LI 	while(i < 4) {
4039fa42a0bfSXin LI 		*acb_device_map = acb->msgcode_rwbuffer[iop_device_map];
4040fa42a0bfSXin LI 		acb_device_map++;
4041fa42a0bfSXin LI 		iop_device_map++;
4042fa42a0bfSXin LI 		i++;
4043fa42a0bfSXin LI 	}
4044fa42a0bfSXin LI 	printf("Areca RAID adapter%d: %s F/W version %s \n", acb->pci_unit, acb->firm_model, acb->firm_version);
4045fa42a0bfSXin LI 	acb->firm_request_len	= acb->msgcode_rwbuffer[1];	/*firm_request_len,   1, 04-07*/
4046fa42a0bfSXin LI 	acb->firm_numbers_queue	= acb->msgcode_rwbuffer[2];	/*firm_numbers_queue, 2, 08-11*/
4047fa42a0bfSXin LI 	acb->firm_sdram_size	= acb->msgcode_rwbuffer[3];	/*firm_sdram_size,    3, 12-15*/
4048fa42a0bfSXin LI 	acb->firm_ide_channels	= acb->msgcode_rwbuffer[4];	/*firm_ide_channels,  4, 16-19*/
4049fa42a0bfSXin LI 	acb->firm_cfg_version	= acb->msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]; /*firm_cfg_version,  25*/
4050fa42a0bfSXin LI 	if(acb->firm_numbers_queue > ARCMSR_MAX_OUTSTANDING_CMD)
4051fa42a0bfSXin LI 		acb->maxOutstanding = ARCMSR_MAX_OUTSTANDING_CMD - 1;
4052fa42a0bfSXin LI 	else
4053fa42a0bfSXin LI 		acb->maxOutstanding = acb->firm_numbers_queue - 1;
4054fa42a0bfSXin LI }
4055fa42a0bfSXin LI /*
4056fa42a0bfSXin LI **********************************************************************
4057fa42a0bfSXin LI **********************************************************************
4058fa42a0bfSXin LI */
405944f05562SScott Long static void arcmsr_get_firmware_spec(struct AdapterControlBlock *acb)
406044f05562SScott Long {
406144f05562SScott Long 	switch (acb->adapter_type) {
4062fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_A:
406344f05562SScott Long 		arcmsr_get_hba_config(acb);
406444f05562SScott Long 		break;
4065fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_B:
406644f05562SScott Long 		arcmsr_get_hbb_config(acb);
406744f05562SScott Long 		break;
4068fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_C:
4069d74001adSXin LI 		arcmsr_get_hbc_config(acb);
4070d74001adSXin LI 		break;
4071fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_D:
40727a7bc959SXin LI 		arcmsr_get_hbd_config(acb);
40737a7bc959SXin LI 		break;
4074fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_E:
4075a1103e04SXin LI 		arcmsr_get_hbe_config(acb);
4076fa42a0bfSXin LI 		break;
4077fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_F:
4078fa42a0bfSXin LI 		arcmsr_get_hbf_config(acb);
4079a1103e04SXin LI 		break;
408044f05562SScott Long 	}
408144f05562SScott Long }
408244f05562SScott Long /*
408344f05562SScott Long **********************************************************************
408444f05562SScott Long **********************************************************************
408544f05562SScott Long */
408644f05562SScott Long static void arcmsr_wait_firmware_ready( struct AdapterControlBlock *acb)
408744f05562SScott Long {
408844f05562SScott Long 	int	timeout=0;
408944f05562SScott Long 
409044f05562SScott Long 	switch (acb->adapter_type) {
409144f05562SScott Long 	case ACB_ADAPTER_TYPE_A: {
4092d74001adSXin LI 			while ((CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_msgaddr1) & ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK) == 0)
409344f05562SScott Long 			{
409444f05562SScott Long 				if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */
409544f05562SScott Long 				{
4096d74001adSXin LI 					printf( "arcmsr%d:timed out waiting for firmware \n", acb->pci_unit);
409744f05562SScott Long 					return;
409844f05562SScott Long 				}
409944f05562SScott Long 				UDELAY(15000); /* wait 15 milli-seconds */
410044f05562SScott Long 			}
410144f05562SScott Long 		}
410244f05562SScott Long 		break;
410344f05562SScott Long 	case ACB_ADAPTER_TYPE_B: {
4104b23a1998SXin LI 			struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
4105b23a1998SXin LI 			while ((READ_CHIP_REG32(0, phbbmu->iop2drv_doorbell) & ARCMSR_MESSAGE_FIRMWARE_OK) == 0)
410644f05562SScott Long 			{
410744f05562SScott Long 				if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */
410844f05562SScott Long 				{
4109d74001adSXin LI 					printf( "arcmsr%d: timed out waiting for firmware \n", acb->pci_unit);
411044f05562SScott Long 					return;
411144f05562SScott Long 				}
411244f05562SScott Long 				UDELAY(15000); /* wait 15 milli-seconds */
411344f05562SScott Long 			}
4114b23a1998SXin LI 			WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT);
4115d74001adSXin LI 		}
4116d74001adSXin LI 		break;
4117d74001adSXin LI 	case ACB_ADAPTER_TYPE_C: {
4118d74001adSXin LI 			while ((CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_msgaddr1) & ARCMSR_HBCMU_MESSAGE_FIRMWARE_OK) == 0)
4119d74001adSXin LI 			{
4120d74001adSXin LI 				if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */
4121d74001adSXin LI 				{
4122d74001adSXin LI 					printf( "arcmsr%d:timed out waiting for firmware ready\n", acb->pci_unit);
4123d74001adSXin LI 					return;
4124d74001adSXin LI 				}
4125d74001adSXin LI 				UDELAY(15000); /* wait 15 milli-seconds */
4126d74001adSXin LI 			}
412744f05562SScott Long 		}
412844f05562SScott Long 		break;
41297a7bc959SXin LI 	case ACB_ADAPTER_TYPE_D: {
41307a7bc959SXin LI 			while ((CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_msgaddr1) & ARCMSR_HBDMU_MESSAGE_FIRMWARE_OK) == 0)
41317a7bc959SXin LI 			{
41327a7bc959SXin LI 				if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */
41337a7bc959SXin LI 				{
41347a7bc959SXin LI 					printf( "arcmsr%d:timed out waiting for firmware ready\n", acb->pci_unit);
41357a7bc959SXin LI 					return;
41367a7bc959SXin LI 				}
41377a7bc959SXin LI 				UDELAY(15000); /* wait 15 milli-seconds */
41387a7bc959SXin LI 			}
41397a7bc959SXin LI 		}
41407a7bc959SXin LI 		break;
4141fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_E:
4142fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_F: {
4143a1103e04SXin LI 			while ((CHIP_REG_READ32(HBE_MessageUnit, 0, outbound_msgaddr1) & ARCMSR_HBEMU_MESSAGE_FIRMWARE_OK) == 0)
4144a1103e04SXin LI 			{
4145a1103e04SXin LI 				if (timeout++ > 4000) /* (4000*15)/1000 = 60 sec */
4146a1103e04SXin LI 				{
4147a1103e04SXin LI 					printf( "arcmsr%d:timed out waiting for firmware ready\n", acb->pci_unit);
4148a1103e04SXin LI 					return;
4149a1103e04SXin LI 				}
4150a1103e04SXin LI 				UDELAY(15000); /* wait 15 milli-seconds */
4151a1103e04SXin LI 			}
4152a1103e04SXin LI 		}
4153a1103e04SXin LI 		break;
415444f05562SScott Long 	}
415544f05562SScott Long }
415644f05562SScott Long /*
415744f05562SScott Long **********************************************************************
415844f05562SScott Long **********************************************************************
415944f05562SScott Long */
416044f05562SScott Long static void arcmsr_clear_doorbell_queue_buffer( struct AdapterControlBlock *acb)
416144f05562SScott Long {
4162d74001adSXin LI 	u_int32_t outbound_doorbell;
4163d74001adSXin LI 
416444f05562SScott Long 	switch (acb->adapter_type) {
416544f05562SScott Long 	case ACB_ADAPTER_TYPE_A: {
416644f05562SScott Long 			/* empty doorbell Qbuffer if door bell ringed */
4167d74001adSXin LI 			outbound_doorbell = CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_doorbell);
4168d74001adSXin LI 			CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_doorbell, outbound_doorbell);	/*clear doorbell interrupt */
4169d74001adSXin LI 			CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK);
417044f05562SScott Long 		}
417144f05562SScott Long 		break;
417244f05562SScott Long 	case ACB_ADAPTER_TYPE_B: {
4173b23a1998SXin LI 			struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
4174fc5ef1caSXin LI 			WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell, ARCMSR_DOORBELL_INT_CLEAR_PATTERN);/*clear interrupt and message state*/
4175b23a1998SXin LI 			WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_READ_OK);
417644f05562SScott Long 			/* let IOP know data has been read */
417744f05562SScott Long 		}
417844f05562SScott Long 		break;
4179d74001adSXin LI 	case ACB_ADAPTER_TYPE_C: {
4180d74001adSXin LI 			/* empty doorbell Qbuffer if door bell ringed */
4181d74001adSXin LI 			outbound_doorbell = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell);
4182d74001adSXin LI 			CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, outbound_doorbell);	/*clear doorbell interrupt */
4183d74001adSXin LI 			CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK);
41847a7bc959SXin LI 			CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell_clear); /* Dummy read to force pci flush */
41857a7bc959SXin LI 			CHIP_REG_READ32(HBC_MessageUnit, 0, inbound_doorbell); /* Dummy read to force pci flush */
41867a7bc959SXin LI 		}
41877a7bc959SXin LI 		break;
41887a7bc959SXin LI 	case ACB_ADAPTER_TYPE_D: {
41897a7bc959SXin LI 			/* empty doorbell Qbuffer if door bell ringed */
41907a7bc959SXin LI 			outbound_doorbell = CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell);
41917a7bc959SXin LI 			CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, outbound_doorbell);	/*clear doorbell interrupt */
41927a7bc959SXin LI 			CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_doorbell, ARCMSR_HBDMU_DRV2IOP_DATA_OUT_READ);
4193d74001adSXin LI 		}
4194d74001adSXin LI 		break;
4195fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_E:
4196fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_F: {
4197a1103e04SXin LI 			/* empty doorbell Qbuffer if door bell ringed */
4198a1103e04SXin LI 			acb->in_doorbell = CHIP_REG_READ32(HBE_MessageUnit, 0, iobound_doorbell);
4199a1103e04SXin LI 			CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_status, 0);	/*clear doorbell interrupt */
4200a1103e04SXin LI 			acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_DATA_READ_OK;
4201a1103e04SXin LI 			CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
4202a1103e04SXin LI 		}
4203a1103e04SXin LI 		break;
420444f05562SScott Long 	}
420544f05562SScott Long }
420644f05562SScott Long /*
420744f05562SScott Long ************************************************************************
420844f05562SScott Long ************************************************************************
420944f05562SScott Long */
421044f05562SScott Long static u_int32_t arcmsr_iop_confirm(struct AdapterControlBlock *acb)
421144f05562SScott Long {
421244f05562SScott Long 	unsigned long srb_phyaddr;
421344f05562SScott Long 	u_int32_t srb_phyaddr_hi32;
42147a7bc959SXin LI 	u_int32_t srb_phyaddr_lo32;
421544f05562SScott Long 
421644f05562SScott Long 	/*
421744f05562SScott Long 	********************************************************************
421844f05562SScott Long 	** here we need to tell iop 331 our freesrb.HighPart
421944f05562SScott Long 	** if freesrb.HighPart is not zero
422044f05562SScott Long 	********************************************************************
422144f05562SScott Long 	*/
4222d74001adSXin LI 	srb_phyaddr = (unsigned long) acb->srb_phyaddr.phyaddr;
4223d74001adSXin LI 	srb_phyaddr_hi32 = acb->srb_phyaddr.B.phyadd_high;
42247a7bc959SXin LI 	srb_phyaddr_lo32 = acb->srb_phyaddr.B.phyadd_low;
422544f05562SScott Long 	switch (acb->adapter_type) {
422644f05562SScott Long 	case ACB_ADAPTER_TYPE_A: {
422744f05562SScott Long 			if(srb_phyaddr_hi32 != 0) {
4228d74001adSXin LI 				CHIP_REG_WRITE32(HBA_MessageUnit, 0, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG);
4229d74001adSXin LI 				CHIP_REG_WRITE32(HBA_MessageUnit, 0, msgcode_rwbuffer[1], srb_phyaddr_hi32);
4230d74001adSXin LI 				CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG);
423144f05562SScott Long 				if(!arcmsr_hba_wait_msgint_ready(acb)) {
4232d74001adSXin LI 					printf( "arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit);
423344f05562SScott Long 					return FALSE;
423444f05562SScott Long 				}
423544f05562SScott Long 			}
423644f05562SScott Long 		}
423744f05562SScott Long 		break;
423844f05562SScott Long 		/*
423944f05562SScott Long 		***********************************************************************
424044f05562SScott Long 		**    if adapter type B, set window of "post command Q"
424144f05562SScott Long 		***********************************************************************
424244f05562SScott Long 		*/
424344f05562SScott Long 	case ACB_ADAPTER_TYPE_B: {
424444f05562SScott Long 			u_int32_t post_queue_phyaddr;
424544f05562SScott Long 			struct HBB_MessageUnit *phbbmu;
424644f05562SScott Long 
424744f05562SScott Long 			phbbmu = (struct HBB_MessageUnit *)acb->pmu;
424844f05562SScott Long 			phbbmu->postq_index = 0;
424944f05562SScott Long 			phbbmu->doneq_index = 0;
4250b23a1998SXin LI 			WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_SET_POST_WINDOW);
425144f05562SScott Long 			if(!arcmsr_hbb_wait_msgint_ready(acb)) {
4252d74001adSXin LI 				printf( "arcmsr%d: 'set window of post command Q' timeout\n", acb->pci_unit);
425344f05562SScott Long 				return FALSE;
425444f05562SScott Long 			}
425522f2616bSXin LI 			post_queue_phyaddr = srb_phyaddr + ARCMSR_SRBS_POOL_SIZE
425644f05562SScott Long 								+ offsetof(struct HBB_MessageUnit, post_qbuffer);
4257d74001adSXin LI 			CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG); /* driver "set config" signature */
4258d74001adSXin LI 			CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[1], srb_phyaddr_hi32); /* normal should be zero */
4259d74001adSXin LI 			CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[2], post_queue_phyaddr); /* postQ size (256+8)*4 */
4260d74001adSXin LI 			CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[3], post_queue_phyaddr+1056); /* doneQ size (256+8)*4 */
4261d74001adSXin LI 			CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[4], 1056); /* srb maxQ size must be --> [(256+8)*4] */
4262b23a1998SXin LI 			WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_SET_CONFIG);
426344f05562SScott Long 			if(!arcmsr_hbb_wait_msgint_ready(acb)) {
426444f05562SScott Long 				printf( "arcmsr%d: 'set command Q window' timeout \n", acb->pci_unit);
426544f05562SScott Long 				return FALSE;
426644f05562SScott Long 			}
4267b23a1998SXin LI 			WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_START_DRIVER_MODE);
426844f05562SScott Long 			if(!arcmsr_hbb_wait_msgint_ready(acb)) {
426944f05562SScott Long 				printf( "arcmsr%d: 'start diver mode' timeout \n", acb->pci_unit);
427044f05562SScott Long 				return FALSE;
427144f05562SScott Long 			}
427244f05562SScott Long 		}
427344f05562SScott Long 		break;
4274d74001adSXin LI 	case ACB_ADAPTER_TYPE_C: {
4275d74001adSXin LI 			if(srb_phyaddr_hi32 != 0) {
4276d74001adSXin LI 				CHIP_REG_WRITE32(HBC_MessageUnit, 0, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG);
4277d74001adSXin LI 				CHIP_REG_WRITE32(HBC_MessageUnit, 0, msgcode_rwbuffer[1], srb_phyaddr_hi32);
4278d74001adSXin LI 				CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG);
4279d74001adSXin LI 				CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell,ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE);
4280d74001adSXin LI 				if(!arcmsr_hbc_wait_msgint_ready(acb)) {
4281d74001adSXin LI 					printf( "arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit);
4282d74001adSXin LI 					return FALSE;
4283d74001adSXin LI 				}
4284d74001adSXin LI 			}
4285d74001adSXin LI 		}
4286d74001adSXin LI 		break;
42877a7bc959SXin LI 	case ACB_ADAPTER_TYPE_D: {
42887a7bc959SXin LI 			u_int32_t post_queue_phyaddr, done_queue_phyaddr;
42897a7bc959SXin LI 			struct HBD_MessageUnit0 *phbdmu;
42907a7bc959SXin LI 
42917a7bc959SXin LI 			phbdmu = (struct HBD_MessageUnit0 *)acb->pmu;
42927a7bc959SXin LI 			phbdmu->postq_index = 0;
42937a7bc959SXin LI 			phbdmu->doneq_index = 0x40FF;
42947a7bc959SXin LI 			post_queue_phyaddr = srb_phyaddr_lo32 + ARCMSR_SRBS_POOL_SIZE
42957a7bc959SXin LI 								+ offsetof(struct HBD_MessageUnit0, post_qbuffer);
42967a7bc959SXin LI 			done_queue_phyaddr = srb_phyaddr_lo32 + ARCMSR_SRBS_POOL_SIZE
42977a7bc959SXin LI 								+ offsetof(struct HBD_MessageUnit0, done_qbuffer);
42987a7bc959SXin LI 			CHIP_REG_WRITE32(HBD_MessageUnit, 0, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG); /* driver "set config" signature */
42997a7bc959SXin LI 			CHIP_REG_WRITE32(HBD_MessageUnit, 0, msgcode_rwbuffer[1], srb_phyaddr_hi32);
43007a7bc959SXin LI 			CHIP_REG_WRITE32(HBD_MessageUnit, 0, msgcode_rwbuffer[2], post_queue_phyaddr); /* postQ base */
43017a7bc959SXin LI 			CHIP_REG_WRITE32(HBD_MessageUnit, 0, msgcode_rwbuffer[3], done_queue_phyaddr); /* doneQ base */
43027a7bc959SXin LI 			CHIP_REG_WRITE32(HBD_MessageUnit, 0, msgcode_rwbuffer[4], 0x100);
43037a7bc959SXin LI 			CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG);
43047a7bc959SXin LI 			if(!arcmsr_hbd_wait_msgint_ready(acb)) {
43057a7bc959SXin LI 				printf( "arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit);
43067a7bc959SXin LI 				return FALSE;
43077a7bc959SXin LI 			}
43087a7bc959SXin LI 		}
43097a7bc959SXin LI 		break;
4310a1103e04SXin LI 	case ACB_ADAPTER_TYPE_E: {
4311a1103e04SXin LI 			u_int32_t cdb_phyaddr_lo32;
4312a1103e04SXin LI 			cdb_phyaddr_lo32 = srb_phyaddr_lo32 + offsetof(struct CommandControlBlock, arcmsr_cdb);
4313a1103e04SXin LI 			CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG);
4314a1103e04SXin LI 			CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[1], ARCMSR_SIGNATURE_1884);
4315a1103e04SXin LI 			CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[2], cdb_phyaddr_lo32);
4316a1103e04SXin LI 			CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[3], srb_phyaddr_hi32);
4317a1103e04SXin LI 			CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[4], SRB_SIZE);
4318a1103e04SXin LI 			cdb_phyaddr_lo32 = srb_phyaddr_lo32 + ARCMSR_SRBS_POOL_SIZE;
4319a1103e04SXin LI 			CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[5], cdb_phyaddr_lo32);
4320a1103e04SXin LI 			CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[6], srb_phyaddr_hi32);
4321a1103e04SXin LI 			CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[7], COMPLETION_Q_POOL_SIZE);
4322a1103e04SXin LI 			CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG);
4323a1103e04SXin LI 			acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
4324a1103e04SXin LI 			CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
4325a1103e04SXin LI 			if(!arcmsr_hbe_wait_msgint_ready(acb)) {
4326a1103e04SXin LI 				printf( "arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit);
4327a1103e04SXin LI 				return FALSE;
4328a1103e04SXin LI 			}
4329a1103e04SXin LI 		}
4330a1103e04SXin LI 		break;
4331fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_F: {
4332fa42a0bfSXin LI 			u_int32_t cdb_phyaddr_lo32;
4333fa42a0bfSXin LI 			cdb_phyaddr_lo32 = srb_phyaddr_lo32 + offsetof(struct CommandControlBlock, arcmsr_cdb);
4334fa42a0bfSXin LI 			acb->msgcode_rwbuffer[0] = ARCMSR_SIGNATURE_SET_CONFIG;
4335fa42a0bfSXin LI 			acb->msgcode_rwbuffer[1] = ARCMSR_SIGNATURE_1886;
4336fa42a0bfSXin LI 			acb->msgcode_rwbuffer[2] = cdb_phyaddr_lo32;
4337fa42a0bfSXin LI 			acb->msgcode_rwbuffer[3] = srb_phyaddr_hi32;
4338fa42a0bfSXin LI 			acb->msgcode_rwbuffer[4] = SRB_SIZE;
4339fa42a0bfSXin LI 			cdb_phyaddr_lo32 = srb_phyaddr_lo32 + ARCMSR_SRBS_POOL_SIZE;
4340fa42a0bfSXin LI 			acb->msgcode_rwbuffer[5] = cdb_phyaddr_lo32;
4341fa42a0bfSXin LI 			acb->msgcode_rwbuffer[6] = srb_phyaddr_hi32;
4342fa42a0bfSXin LI 			acb->msgcode_rwbuffer[7] = COMPLETION_Q_POOL_SIZE;
4343fa42a0bfSXin LI 			CHIP_REG_WRITE32(HBF_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG);
4344fa42a0bfSXin LI 			acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
4345fa42a0bfSXin LI 			CHIP_REG_WRITE32(HBF_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
4346fa42a0bfSXin LI 			if(!arcmsr_hbe_wait_msgint_ready(acb)) {
4347fa42a0bfSXin LI 				printf( "arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit);
4348fa42a0bfSXin LI 				return FALSE;
4349fa42a0bfSXin LI 			}
4350fa42a0bfSXin LI 		}
4351fa42a0bfSXin LI 		break;
435244f05562SScott Long 	}
4353dac36688SXin LI 	return (TRUE);
435444f05562SScott Long }
435544f05562SScott Long /*
435644f05562SScott Long ************************************************************************
435744f05562SScott Long ************************************************************************
435844f05562SScott Long */
435944f05562SScott Long static void arcmsr_enable_eoi_mode(struct AdapterControlBlock *acb)
436044f05562SScott Long {
4361a1103e04SXin LI 	if (acb->adapter_type == ACB_ADAPTER_TYPE_B)
436244f05562SScott Long 	{
4363b23a1998SXin LI 		struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
4364b23a1998SXin LI 		WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_ACTIVE_EOI_MODE);
436544f05562SScott Long 		if(!arcmsr_hbb_wait_msgint_ready(acb)) {
4366d74001adSXin LI 			printf( "arcmsr%d: 'iop enable eoi mode' timeout \n", acb->pci_unit);
436744f05562SScott Long 			return;
436844f05562SScott Long 		}
436944f05562SScott Long 	}
437044f05562SScott Long }
437144f05562SScott Long /*
437244f05562SScott Long **********************************************************************
4373ad6d6297SScott Long **********************************************************************
4374ad6d6297SScott Long */
4375ad6d6297SScott Long static void arcmsr_iop_init(struct AdapterControlBlock *acb)
4376ad6d6297SScott Long {
437744f05562SScott Long 	u_int32_t intmask_org;
4378ad6d6297SScott Long 
437944f05562SScott Long 	/* disable all outbound interrupt */
438044f05562SScott Long 	intmask_org = arcmsr_disable_allintr(acb);
438144f05562SScott Long 	arcmsr_wait_firmware_ready(acb);
438244f05562SScott Long 	arcmsr_iop_confirm(acb);
4383ad6d6297SScott Long 	arcmsr_get_firmware_spec(acb);
438444f05562SScott Long 	/*start background rebuild*/
4385ad6d6297SScott Long 	arcmsr_start_adapter_bgrb(acb);
438644f05562SScott Long 	/* empty doorbell Qbuffer if door bell ringed */
438744f05562SScott Long 	arcmsr_clear_doorbell_queue_buffer(acb);
438844f05562SScott Long 	arcmsr_enable_eoi_mode(acb);
438944f05562SScott Long 	/* enable outbound Post Queue, outbound doorbell Interrupt */
439044f05562SScott Long 	arcmsr_enable_allintr(acb, intmask_org);
4391ad6d6297SScott Long 	acb->acb_flags |= ACB_F_IOP_INITED;
4392ad6d6297SScott Long }
4393ad6d6297SScott Long /*
4394ad6d6297SScott Long **********************************************************************
4395f1c579b1SScott Long **********************************************************************
4396f1c579b1SScott Long */
4397231c8b71SXin LI static void arcmsr_map_free_srb(void *arg, bus_dma_segment_t *segs, int nseg, int error)
4398f1c579b1SScott Long {
4399ad6d6297SScott Long 	struct AdapterControlBlock *acb = arg;
4400ad6d6297SScott Long 	struct CommandControlBlock *srb_tmp;
440144f05562SScott Long 	u_int32_t i;
4402ad6d6297SScott Long 	unsigned long srb_phyaddr = (unsigned long)segs->ds_addr;
4403f1c579b1SScott Long 
4404d74001adSXin LI 	acb->srb_phyaddr.phyaddr = srb_phyaddr;
44057a7bc959SXin LI 	srb_tmp = (struct CommandControlBlock *)acb->uncacheptr;
4406ad6d6297SScott Long 	for(i=0; i < ARCMSR_MAX_FREESRB_NUM; i++) {
440744f05562SScott Long 		if(bus_dmamap_create(acb->dm_segs_dmat,
440844f05562SScott Long 			 /*flags*/0, &srb_tmp->dm_segs_dmamap) != 0) {
4409ad6d6297SScott Long 			acb->acb_flags |= ACB_F_MAPFREESRB_FAILD;
441044f05562SScott Long 			printf("arcmsr%d:"
441144f05562SScott Long 			" srb dmamap bus_dmamap_create error\n", acb->pci_unit);
4412ad6d6297SScott Long 			return;
4413ad6d6297SScott Long 		}
4414a1103e04SXin LI 		if((acb->adapter_type == ACB_ADAPTER_TYPE_C) || (acb->adapter_type == ACB_ADAPTER_TYPE_D)
4415fa42a0bfSXin LI 			 || (acb->adapter_type == ACB_ADAPTER_TYPE_E) || (acb->adapter_type == ACB_ADAPTER_TYPE_F))
44167a7bc959SXin LI 		{
44177a7bc959SXin LI 			srb_tmp->cdb_phyaddr_low = srb_phyaddr;
44187a7bc959SXin LI 			srb_tmp->cdb_phyaddr_high = (u_int32_t)((srb_phyaddr >> 16) >> 16);
44197a7bc959SXin LI 		}
44207a7bc959SXin LI 		else
44217a7bc959SXin LI 			srb_tmp->cdb_phyaddr_low = srb_phyaddr >> 5;
4422ad6d6297SScott Long 		srb_tmp->acb = acb;
4423a1103e04SXin LI 		srb_tmp->smid = i << 16;
4424ad6d6297SScott Long 		acb->srbworkingQ[i] = acb->psrb_pool[i] = srb_tmp;
442522f2616bSXin LI 		srb_phyaddr = srb_phyaddr + SRB_SIZE;
442622f2616bSXin LI 		srb_tmp = (struct CommandControlBlock *)((unsigned long)srb_tmp + SRB_SIZE);
4427ad6d6297SScott Long 	}
4428fc5ef1caSXin LI 	if (acb->adapter_type == ACB_ADAPTER_TYPE_E)
4429a1103e04SXin LI 		acb->pCompletionQ = (pCompletion_Q)srb_tmp;
4430fa42a0bfSXin LI 	else if (acb->adapter_type == ACB_ADAPTER_TYPE_F) {
4431fa42a0bfSXin LI 		acb->pCompletionQ = (pCompletion_Q)srb_tmp;
4432fa42a0bfSXin LI 		acb->completeQ_phys = srb_phyaddr;
4433fa42a0bfSXin LI 		memset(acb->pCompletionQ, 0xff, COMPLETION_Q_POOL_SIZE);
4434fa42a0bfSXin LI 		acb->message_wbuffer = (u_int32_t *)((unsigned long)acb->pCompletionQ + COMPLETION_Q_POOL_SIZE);
4435fa42a0bfSXin LI 		acb->message_rbuffer = (u_int32_t *)((unsigned long)acb->message_wbuffer + 0x100);
4436fa42a0bfSXin LI 		acb->msgcode_rwbuffer = (u_int32_t *)((unsigned long)acb->message_wbuffer + 0x200);
4437fa42a0bfSXin LI 		memset((void *)acb->message_wbuffer, 0, MESG_RW_BUFFER_SIZE);
4438fa42a0bfSXin LI 	}
4439ad6d6297SScott Long 	acb->vir2phy_offset = (unsigned long)srb_tmp - (unsigned long)srb_phyaddr;
4440f1c579b1SScott Long }
4441f1c579b1SScott Long /*
4442f1c579b1SScott Long ************************************************************************
4443f1c579b1SScott Long ************************************************************************
4444f1c579b1SScott Long */
4445ad6d6297SScott Long static void arcmsr_free_resource(struct AdapterControlBlock *acb)
4446f1c579b1SScott Long {
4447f1c579b1SScott Long 	/* remove the control device */
4448ad6d6297SScott Long 	if(acb->ioctl_dev != NULL) {
4449ad6d6297SScott Long 		destroy_dev(acb->ioctl_dev);
4450f1c579b1SScott Long 	}
4451ad6d6297SScott Long 	bus_dmamap_unload(acb->srb_dmat, acb->srb_dmamap);
4452ad6d6297SScott Long 	bus_dmamap_destroy(acb->srb_dmat, acb->srb_dmamap);
4453ad6d6297SScott Long 	bus_dma_tag_destroy(acb->srb_dmat);
4454ad6d6297SScott Long 	bus_dma_tag_destroy(acb->dm_segs_dmat);
4455ad6d6297SScott Long 	bus_dma_tag_destroy(acb->parent_dmat);
4456f1c579b1SScott Long }
4457f1c579b1SScott Long /*
4458f1c579b1SScott Long ************************************************************************
4459f1c579b1SScott Long ************************************************************************
4460f1c579b1SScott Long */
44617a7bc959SXin LI static void arcmsr_mutex_init(struct AdapterControlBlock *acb)
44627a7bc959SXin LI {
44637a7bc959SXin LI 	ARCMSR_LOCK_INIT(&acb->isr_lock, "arcmsr isr lock");
44647a7bc959SXin LI 	ARCMSR_LOCK_INIT(&acb->srb_lock, "arcmsr srb lock");
44657a7bc959SXin LI 	ARCMSR_LOCK_INIT(&acb->postDone_lock, "arcmsr postQ lock");
44667a7bc959SXin LI 	ARCMSR_LOCK_INIT(&acb->qbuffer_lock, "arcmsr RW buffer lock");
44677a7bc959SXin LI }
44687a7bc959SXin LI /*
44697a7bc959SXin LI ************************************************************************
44707a7bc959SXin LI ************************************************************************
44717a7bc959SXin LI */
44727a7bc959SXin LI static void arcmsr_mutex_destroy(struct AdapterControlBlock *acb)
44737a7bc959SXin LI {
44747a7bc959SXin LI 	ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock);
44757a7bc959SXin LI 	ARCMSR_LOCK_DESTROY(&acb->postDone_lock);
44767a7bc959SXin LI 	ARCMSR_LOCK_DESTROY(&acb->srb_lock);
44777a7bc959SXin LI 	ARCMSR_LOCK_DESTROY(&acb->isr_lock);
44787a7bc959SXin LI }
44797a7bc959SXin LI /*
44807a7bc959SXin LI ************************************************************************
44817a7bc959SXin LI ************************************************************************
44827a7bc959SXin LI */
4483ad6d6297SScott Long static u_int32_t arcmsr_initialize(device_t dev)
4484f1c579b1SScott Long {
4485ad6d6297SScott Long 	struct AdapterControlBlock *acb = device_get_softc(dev);
4486ad6d6297SScott Long 	u_int16_t pci_command;
448744f05562SScott Long 	int i, j,max_coherent_size;
4488dac36688SXin LI 	u_int32_t vendor_dev_id;
4489f1c579b1SScott Long 
4490dac36688SXin LI 	vendor_dev_id = pci_get_devid(dev);
4491dac36688SXin LI 	acb->vendor_device_id = vendor_dev_id;
4492224a78aeSXin LI 	acb->sub_device_id = pci_read_config(dev, PCIR_SUBDEV_0, 2);
4493dac36688SXin LI 	switch (vendor_dev_id) {
4494dac36688SXin LI 	case PCIDevVenIDARC1880:
4495dac36688SXin LI 	case PCIDevVenIDARC1882:
4496dac36688SXin LI 	case PCIDevVenIDARC1213:
4497dac36688SXin LI 	case PCIDevVenIDARC1223: {
4498d74001adSXin LI 			acb->adapter_type = ACB_ADAPTER_TYPE_C;
4499fc5ef1caSXin LI 			if ((acb->sub_device_id == ARECA_SUB_DEV_ID_1883) ||
4500fc5ef1caSXin LI 			    (acb->sub_device_id == ARECA_SUB_DEV_ID_1216) ||
4501fc5ef1caSXin LI 			    (acb->sub_device_id == ARECA_SUB_DEV_ID_1226))
4502224a78aeSXin LI 				acb->adapter_bus_speed = ACB_BUS_SPEED_12G;
4503224a78aeSXin LI 			else
4504dac36688SXin LI 				acb->adapter_bus_speed = ACB_BUS_SPEED_6G;
4505d74001adSXin LI 			max_coherent_size = ARCMSR_SRBS_POOL_SIZE;
4506d74001adSXin LI 		}
4507d74001adSXin LI 		break;
4508a1103e04SXin LI 	case PCIDevVenIDARC1884:
4509a1103e04SXin LI 		acb->adapter_type = ACB_ADAPTER_TYPE_E;
4510a1103e04SXin LI 		acb->adapter_bus_speed = ACB_BUS_SPEED_12G;
4511a1103e04SXin LI 		max_coherent_size = ARCMSR_SRBS_POOL_SIZE + COMPLETION_Q_POOL_SIZE;
4512a1103e04SXin LI 		acb->completionQ_entry = COMPLETION_Q_POOL_SIZE / sizeof(struct deliver_completeQ);
4513a1103e04SXin LI 		break;
4514fa42a0bfSXin LI 	case PCIDevVenIDARC1886_:
4515fa42a0bfSXin LI 	case PCIDevVenIDARC1886:
4516fa42a0bfSXin LI 		acb->adapter_type = ACB_ADAPTER_TYPE_F;
4517fa42a0bfSXin LI 		acb->adapter_bus_speed = ACB_BUS_SPEED_12G;
4518fa42a0bfSXin LI 		max_coherent_size = ARCMSR_SRBS_POOL_SIZE + COMPLETION_Q_POOL_SIZE + MESG_RW_BUFFER_SIZE;
4519fa42a0bfSXin LI 		acb->completionQ_entry = COMPLETION_Q_POOL_SIZE / sizeof(struct deliver_completeQ);
4520fa42a0bfSXin LI 		break;
45217a7bc959SXin LI 	case PCIDevVenIDARC1214: {
45227a7bc959SXin LI 			acb->adapter_type = ACB_ADAPTER_TYPE_D;
45237a7bc959SXin LI 			acb->adapter_bus_speed = ACB_BUS_SPEED_6G;
45247a7bc959SXin LI 			max_coherent_size = ARCMSR_SRBS_POOL_SIZE + (sizeof(struct HBD_MessageUnit0));
45257a7bc959SXin LI 		}
45267a7bc959SXin LI 		break;
4527231c8b71SXin LI 	case PCIDevVenIDARC1200:
452844f05562SScott Long 	case PCIDevVenIDARC1201: {
452944f05562SScott Long 			acb->adapter_type = ACB_ADAPTER_TYPE_B;
4530dac36688SXin LI 			acb->adapter_bus_speed = ACB_BUS_SPEED_3G;
4531d74001adSXin LI 			max_coherent_size = ARCMSR_SRBS_POOL_SIZE + (sizeof(struct HBB_MessageUnit));
453244f05562SScott Long 		}
453344f05562SScott Long 		break;
4534b23a1998SXin LI 	case PCIDevVenIDARC1203: {
4535b23a1998SXin LI 			acb->adapter_type = ACB_ADAPTER_TYPE_B;
4536b23a1998SXin LI 			acb->adapter_bus_speed = ACB_BUS_SPEED_6G;
4537b23a1998SXin LI 			max_coherent_size = ARCMSR_SRBS_POOL_SIZE + (sizeof(struct HBB_MessageUnit));
4538b23a1998SXin LI 		}
4539b23a1998SXin LI 		break;
454044f05562SScott Long 	case PCIDevVenIDARC1110:
454144f05562SScott Long 	case PCIDevVenIDARC1120:
454244f05562SScott Long 	case PCIDevVenIDARC1130:
454344f05562SScott Long 	case PCIDevVenIDARC1160:
454444f05562SScott Long 	case PCIDevVenIDARC1170:
454544f05562SScott Long 	case PCIDevVenIDARC1210:
454644f05562SScott Long 	case PCIDevVenIDARC1220:
454744f05562SScott Long 	case PCIDevVenIDARC1230:
4548231c8b71SXin LI 	case PCIDevVenIDARC1231:
454944f05562SScott Long 	case PCIDevVenIDARC1260:
4550231c8b71SXin LI 	case PCIDevVenIDARC1261:
455144f05562SScott Long 	case PCIDevVenIDARC1270:
455244f05562SScott Long 	case PCIDevVenIDARC1280:
4553d74001adSXin LI 	case PCIDevVenIDARC1212:
4554d74001adSXin LI 	case PCIDevVenIDARC1222:
455544f05562SScott Long 	case PCIDevVenIDARC1380:
455644f05562SScott Long 	case PCIDevVenIDARC1381:
455744f05562SScott Long 	case PCIDevVenIDARC1680:
455844f05562SScott Long 	case PCIDevVenIDARC1681: {
455944f05562SScott Long 			acb->adapter_type = ACB_ADAPTER_TYPE_A;
4560dac36688SXin LI 			acb->adapter_bus_speed = ACB_BUS_SPEED_3G;
456144f05562SScott Long 			max_coherent_size = ARCMSR_SRBS_POOL_SIZE;
456244f05562SScott Long 		}
456344f05562SScott Long 		break;
456444f05562SScott Long 	default: {
456544f05562SScott Long 			printf("arcmsr%d:"
456644f05562SScott Long 			" unknown RAID adapter type \n", device_get_unit(dev));
456744f05562SScott Long 			return ENOMEM;
456844f05562SScott Long 		}
456944f05562SScott Long 	}
4570b6f97155SScott Long 	if(bus_dma_tag_create(  /*PCI parent*/		bus_get_dma_tag(dev),
4571f1c579b1SScott Long 				/*alignemnt*/		1,
4572f1c579b1SScott Long 				/*boundary*/		0,
4573701d9f1fSScott Long 				/*lowaddr*/		BUS_SPACE_MAXADDR,
4574f1c579b1SScott Long 				/*highaddr*/		BUS_SPACE_MAXADDR,
4575f1c579b1SScott Long 				/*filter*/		NULL,
4576f1c579b1SScott Long 				/*filterarg*/		NULL,
4577f1c579b1SScott Long 				/*maxsize*/		BUS_SPACE_MAXSIZE_32BIT,
4578f1c579b1SScott Long 				/*nsegments*/		BUS_SPACE_UNRESTRICTED,
4579f1c579b1SScott Long 				/*maxsegsz*/		BUS_SPACE_MAXSIZE_32BIT,
4580f1c579b1SScott Long 				/*flags*/		0,
4581f1c579b1SScott Long 				/*lockfunc*/		NULL,
4582f1c579b1SScott Long 				/*lockarg*/		NULL,
4583231c8b71SXin LI 							&acb->parent_dmat) != 0)
4584f1c579b1SScott Long 	{
458544f05562SScott Long 		printf("arcmsr%d: parent_dmat bus_dma_tag_create failure!\n", device_get_unit(dev));
4586f1c579b1SScott Long 		return ENOMEM;
4587f1c579b1SScott Long 	}
4588231c8b71SXin LI 
4589f1c579b1SScott Long 	/* Create a single tag describing a region large enough to hold all of the s/g lists we will need. */
4590ad6d6297SScott Long 	if(bus_dma_tag_create(  /*parent_dmat*/		acb->parent_dmat,
4591f1c579b1SScott Long 				/*alignment*/		1,
4592f1c579b1SScott Long 				/*boundary*/		0,
459322f2616bSXin LI #ifdef PAE
459422f2616bSXin LI 				/*lowaddr*/		BUS_SPACE_MAXADDR_32BIT,
459522f2616bSXin LI #else
4596f1c579b1SScott Long 				/*lowaddr*/		BUS_SPACE_MAXADDR,
459722f2616bSXin LI #endif
4598f1c579b1SScott Long 				/*highaddr*/		BUS_SPACE_MAXADDR,
4599f1c579b1SScott Long 				/*filter*/		NULL,
4600f1c579b1SScott Long 				/*filterarg*/		NULL,
4601231c8b71SXin LI 				/*maxsize*/		ARCMSR_MAX_SG_ENTRIES * PAGE_SIZE * ARCMSR_MAX_FREESRB_NUM,
4602f1c579b1SScott Long 				/*nsegments*/		ARCMSR_MAX_SG_ENTRIES,
4603f1c579b1SScott Long 				/*maxsegsz*/		BUS_SPACE_MAXSIZE_32BIT,
4604ad6d6297SScott Long 				/*flags*/		0,
4605f1c579b1SScott Long 				/*lockfunc*/		busdma_lock_mutex,
46067a7bc959SXin LI 				/*lockarg*/		&acb->isr_lock,
4607231c8b71SXin LI 							&acb->dm_segs_dmat) != 0)
4608f1c579b1SScott Long 	{
4609ad6d6297SScott Long 		bus_dma_tag_destroy(acb->parent_dmat);
461044f05562SScott Long 		printf("arcmsr%d: dm_segs_dmat bus_dma_tag_create failure!\n", device_get_unit(dev));
4611f1c579b1SScott Long 		return ENOMEM;
4612f1c579b1SScott Long 	}
4613231c8b71SXin LI 
4614ad6d6297SScott Long 	/* DMA tag for our srb structures.... Allocate the freesrb memory */
4615ad6d6297SScott Long 	if(bus_dma_tag_create(  /*parent_dmat*/		acb->parent_dmat,
461644f05562SScott Long 				/*alignment*/		0x20,
4617f1c579b1SScott Long 				/*boundary*/		0,
4618f1c579b1SScott Long 				/*lowaddr*/		BUS_SPACE_MAXADDR_32BIT,
4619f1c579b1SScott Long 				/*highaddr*/		BUS_SPACE_MAXADDR,
4620f1c579b1SScott Long 				/*filter*/		NULL,
4621f1c579b1SScott Long 				/*filterarg*/		NULL,
462244f05562SScott Long 				/*maxsize*/		max_coherent_size,
4623f1c579b1SScott Long 				/*nsegments*/		1,
4624f1c579b1SScott Long 				/*maxsegsz*/		BUS_SPACE_MAXSIZE_32BIT,
4625701d9f1fSScott Long 				/*flags*/		0,
4626f1c579b1SScott Long 				/*lockfunc*/		NULL,
4627f1c579b1SScott Long 				/*lockarg*/		NULL,
4628231c8b71SXin LI 							&acb->srb_dmat) != 0)
4629f1c579b1SScott Long 	{
4630ad6d6297SScott Long 		bus_dma_tag_destroy(acb->dm_segs_dmat);
4631ad6d6297SScott Long 		bus_dma_tag_destroy(acb->parent_dmat);
463244f05562SScott Long 		printf("arcmsr%d: srb_dmat bus_dma_tag_create failure!\n", device_get_unit(dev));
4633f1c579b1SScott Long 		return ENXIO;
4634f1c579b1SScott Long 	}
4635f1c579b1SScott Long 	/* Allocation for our srbs */
4636d74001adSXin LI 	if(bus_dmamem_alloc(acb->srb_dmat, (void **)&acb->uncacheptr, BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_ZERO, &acb->srb_dmamap) != 0) {
4637ad6d6297SScott Long 		bus_dma_tag_destroy(acb->srb_dmat);
4638ad6d6297SScott Long 		bus_dma_tag_destroy(acb->dm_segs_dmat);
4639ad6d6297SScott Long 		bus_dma_tag_destroy(acb->parent_dmat);
464044f05562SScott Long 		printf("arcmsr%d: srb_dmat bus_dmamem_alloc failure!\n", device_get_unit(dev));
4641f1c579b1SScott Long 		return ENXIO;
4642f1c579b1SScott Long 	}
4643f1c579b1SScott Long 	/* And permanently map them */
4644231c8b71SXin LI 	if(bus_dmamap_load(acb->srb_dmat, acb->srb_dmamap, acb->uncacheptr, max_coherent_size, arcmsr_map_free_srb, acb, /*flags*/0)) {
4645ad6d6297SScott Long 		bus_dma_tag_destroy(acb->srb_dmat);
4646ad6d6297SScott Long 		bus_dma_tag_destroy(acb->dm_segs_dmat);
4647ad6d6297SScott Long 		bus_dma_tag_destroy(acb->parent_dmat);
464844f05562SScott Long 		printf("arcmsr%d: srb_dmat bus_dmamap_load failure!\n", device_get_unit(dev));
4649f1c579b1SScott Long 		return ENXIO;
4650f1c579b1SScott Long 	}
4651f1c579b1SScott Long 	pci_command = pci_read_config(dev, PCIR_COMMAND, 2);
4652f1c579b1SScott Long 	pci_command |= PCIM_CMD_BUSMASTEREN;
4653f1c579b1SScott Long 	pci_command |= PCIM_CMD_PERRESPEN;
4654f1c579b1SScott Long 	pci_command |= PCIM_CMD_MWRICEN;
4655c68534f1SScott Long 	/* Enable Busmaster */
4656f1c579b1SScott Long 	pci_write_config(dev, PCIR_COMMAND, pci_command, 2);
465744f05562SScott Long 	switch(acb->adapter_type) {
465844f05562SScott Long 	case ACB_ADAPTER_TYPE_A: {
465944f05562SScott Long 		u_int32_t rid0 = PCIR_BAR(0);
466044f05562SScott Long 		vm_offset_t	mem_base0;
466144f05562SScott Long 
4662eff83876SJustin Hibbits 		acb->sys_res_arcmsr[0] = bus_alloc_resource_any(dev,SYS_RES_MEMORY, &rid0, RF_ACTIVE);
466344f05562SScott Long 		if(acb->sys_res_arcmsr[0] == NULL) {
4664ad6d6297SScott Long 			arcmsr_free_resource(acb);
4665d74001adSXin LI 			printf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev));
4666f1c579b1SScott Long 			return ENOMEM;
4667f1c579b1SScott Long 		}
466844f05562SScott Long 		if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) {
4669ad6d6297SScott Long 			arcmsr_free_resource(acb);
4670d74001adSXin LI 			printf("arcmsr%d: rman_get_start failure!\n", device_get_unit(dev));
4671f1c579b1SScott Long 			return ENXIO;
4672f1c579b1SScott Long 		}
467344f05562SScott Long 		mem_base0 = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]);
467444f05562SScott Long 		if(mem_base0 == 0) {
4675ad6d6297SScott Long 			arcmsr_free_resource(acb);
4676d74001adSXin LI 			printf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev));
4677f1c579b1SScott Long 			return ENXIO;
4678f1c579b1SScott Long 		}
467944f05562SScott Long 		acb->btag[0] = rman_get_bustag(acb->sys_res_arcmsr[0]);
468044f05562SScott Long 		acb->bhandle[0] = rman_get_bushandle(acb->sys_res_arcmsr[0]);
468144f05562SScott Long 		acb->pmu = (struct MessageUnit_UNION *)mem_base0;
4682fc5ef1caSXin LI 		acb->rid[0] = rid0;
468344f05562SScott Long 		}
468444f05562SScott Long 		break;
468544f05562SScott Long 	case ACB_ADAPTER_TYPE_B: {
468644f05562SScott Long 		struct HBB_MessageUnit *phbbmu;
468744f05562SScott Long 		struct CommandControlBlock *freesrb;
468844f05562SScott Long 		u_int32_t rid[]={ PCIR_BAR(0), PCIR_BAR(2) };
468944f05562SScott Long 		vm_offset_t	mem_base[]={0,0};
469044f05562SScott Long 		for(i=0; i < 2; i++) {
4691fc5ef1caSXin LI 			acb->sys_res_arcmsr[i] = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid[i], RF_ACTIVE);
469244f05562SScott Long 			if(acb->sys_res_arcmsr[i] == NULL) {
469344f05562SScott Long 				arcmsr_free_resource(acb);
4694d74001adSXin LI 				printf("arcmsr%d: bus_alloc_resource %d failure!\n", device_get_unit(dev), i);
469544f05562SScott Long 				return ENOMEM;
469644f05562SScott Long 			}
469744f05562SScott Long 			if(rman_get_start(acb->sys_res_arcmsr[i]) <= 0) {
469844f05562SScott Long 				arcmsr_free_resource(acb);
4699d74001adSXin LI 				printf("arcmsr%d: rman_get_start %d failure!\n", device_get_unit(dev), i);
470044f05562SScott Long 				return ENXIO;
470144f05562SScott Long 			}
470244f05562SScott Long 			mem_base[i] = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[i]);
470344f05562SScott Long 			if(mem_base[i] == 0) {
470444f05562SScott Long 				arcmsr_free_resource(acb);
4705d74001adSXin LI 				printf("arcmsr%d: rman_get_virtual %d failure!\n", device_get_unit(dev), i);
470644f05562SScott Long 				return ENXIO;
470744f05562SScott Long 			}
470844f05562SScott Long 			acb->btag[i] = rman_get_bustag(acb->sys_res_arcmsr[i]);
470944f05562SScott Long 			acb->bhandle[i] = rman_get_bushandle(acb->sys_res_arcmsr[i]);
471044f05562SScott Long 		}
471144f05562SScott Long 		freesrb = (struct CommandControlBlock *)acb->uncacheptr;
471222f2616bSXin LI 		acb->pmu = (struct MessageUnit_UNION *)((unsigned long)freesrb+ARCMSR_SRBS_POOL_SIZE);
471344f05562SScott Long 		phbbmu = (struct HBB_MessageUnit *)acb->pmu;
471444f05562SScott Long 		phbbmu->hbb_doorbell = (struct HBB_DOORBELL *)mem_base[0];
471544f05562SScott Long 		phbbmu->hbb_rwbuffer = (struct HBB_RWBUFFER *)mem_base[1];
4716b23a1998SXin LI 		if (vendor_dev_id == PCIDevVenIDARC1203) {
4717b23a1998SXin LI 			phbbmu->drv2iop_doorbell = offsetof(struct HBB_DOORBELL_1203, drv2iop_doorbell);
4718b23a1998SXin LI 			phbbmu->drv2iop_doorbell_mask = offsetof(struct HBB_DOORBELL_1203, drv2iop_doorbell_mask);
4719b23a1998SXin LI 			phbbmu->iop2drv_doorbell = offsetof(struct HBB_DOORBELL_1203, iop2drv_doorbell);
4720b23a1998SXin LI 			phbbmu->iop2drv_doorbell_mask = offsetof(struct HBB_DOORBELL_1203, iop2drv_doorbell_mask);
4721b23a1998SXin LI 		} else {
4722b23a1998SXin LI 			phbbmu->drv2iop_doorbell = offsetof(struct HBB_DOORBELL, drv2iop_doorbell);
4723b23a1998SXin LI 			phbbmu->drv2iop_doorbell_mask = offsetof(struct HBB_DOORBELL, drv2iop_doorbell_mask);
4724b23a1998SXin LI 			phbbmu->iop2drv_doorbell = offsetof(struct HBB_DOORBELL, iop2drv_doorbell);
4725b23a1998SXin LI 			phbbmu->iop2drv_doorbell_mask = offsetof(struct HBB_DOORBELL, iop2drv_doorbell_mask);
4726b23a1998SXin LI 		}
4727fc5ef1caSXin LI 		acb->rid[0] = rid[0];
4728fc5ef1caSXin LI 		acb->rid[1] = rid[1];
472944f05562SScott Long 		}
473044f05562SScott Long 		break;
4731d74001adSXin LI 	case ACB_ADAPTER_TYPE_C: {
4732d74001adSXin LI 		u_int32_t rid0 = PCIR_BAR(1);
4733d74001adSXin LI 		vm_offset_t	mem_base0;
4734d74001adSXin LI 
4735eff83876SJustin Hibbits 		acb->sys_res_arcmsr[0] = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid0, RF_ACTIVE);
4736d74001adSXin LI 		if(acb->sys_res_arcmsr[0] == NULL) {
4737d74001adSXin LI 			arcmsr_free_resource(acb);
4738d74001adSXin LI 			printf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev));
4739d74001adSXin LI 			return ENOMEM;
4740d74001adSXin LI 		}
4741d74001adSXin LI 		if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) {
4742d74001adSXin LI 			arcmsr_free_resource(acb);
4743d74001adSXin LI 			printf("arcmsr%d: rman_get_start failure!\n", device_get_unit(dev));
4744d74001adSXin LI 			return ENXIO;
4745d74001adSXin LI 		}
4746d74001adSXin LI 		mem_base0 = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]);
4747d74001adSXin LI 		if(mem_base0 == 0) {
4748d74001adSXin LI 			arcmsr_free_resource(acb);
4749d74001adSXin LI 			printf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev));
4750d74001adSXin LI 			return ENXIO;
4751d74001adSXin LI 		}
4752d74001adSXin LI 		acb->btag[0] = rman_get_bustag(acb->sys_res_arcmsr[0]);
4753d74001adSXin LI 		acb->bhandle[0] = rman_get_bushandle(acb->sys_res_arcmsr[0]);
4754d74001adSXin LI 		acb->pmu = (struct MessageUnit_UNION *)mem_base0;
4755fc5ef1caSXin LI 		acb->rid[0] = rid0;
4756d74001adSXin LI 		}
4757d74001adSXin LI 		break;
47587a7bc959SXin LI 	case ACB_ADAPTER_TYPE_D: {
47597a7bc959SXin LI 		struct HBD_MessageUnit0 *phbdmu;
47607a7bc959SXin LI 		u_int32_t rid0 = PCIR_BAR(0);
47617a7bc959SXin LI 		vm_offset_t	mem_base0;
47627a7bc959SXin LI 
4763eff83876SJustin Hibbits 		acb->sys_res_arcmsr[0] = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid0, RF_ACTIVE);
47647a7bc959SXin LI 		if(acb->sys_res_arcmsr[0] == NULL) {
47657a7bc959SXin LI 			arcmsr_free_resource(acb);
47667a7bc959SXin LI 			printf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev));
47677a7bc959SXin LI 			return ENOMEM;
47687a7bc959SXin LI 		}
47697a7bc959SXin LI 		if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) {
47707a7bc959SXin LI 			arcmsr_free_resource(acb);
47717a7bc959SXin LI 			printf("arcmsr%d: rman_get_start failure!\n", device_get_unit(dev));
47727a7bc959SXin LI 			return ENXIO;
47737a7bc959SXin LI 		}
47747a7bc959SXin LI 		mem_base0 = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]);
47757a7bc959SXin LI 		if(mem_base0 == 0) {
47767a7bc959SXin LI 			arcmsr_free_resource(acb);
47777a7bc959SXin LI 			printf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev));
47787a7bc959SXin LI 			return ENXIO;
47797a7bc959SXin LI 		}
47807a7bc959SXin LI 		acb->btag[0] = rman_get_bustag(acb->sys_res_arcmsr[0]);
47817a7bc959SXin LI 		acb->bhandle[0] = rman_get_bushandle(acb->sys_res_arcmsr[0]);
47827a7bc959SXin LI 		acb->pmu = (struct MessageUnit_UNION *)((unsigned long)acb->uncacheptr+ARCMSR_SRBS_POOL_SIZE);
47837a7bc959SXin LI 		phbdmu = (struct HBD_MessageUnit0 *)acb->pmu;
47847a7bc959SXin LI 		phbdmu->phbdmu = (struct HBD_MessageUnit *)mem_base0;
4785fc5ef1caSXin LI 		acb->rid[0] = rid0;
4786a1103e04SXin LI 		}
4787a1103e04SXin LI 		break;
4788a1103e04SXin LI 	case ACB_ADAPTER_TYPE_E: {
4789a1103e04SXin LI 		u_int32_t rid0 = PCIR_BAR(1);
4790a1103e04SXin LI 		vm_offset_t	mem_base0;
4791a1103e04SXin LI 
4792fc5ef1caSXin LI 		acb->sys_res_arcmsr[0] = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid0, RF_ACTIVE);
4793a1103e04SXin LI 		if(acb->sys_res_arcmsr[0] == NULL) {
4794a1103e04SXin LI 			arcmsr_free_resource(acb);
4795a1103e04SXin LI 			printf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev));
4796a1103e04SXin LI 			return ENOMEM;
4797a1103e04SXin LI 		}
4798a1103e04SXin LI 		if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) {
4799a1103e04SXin LI 			arcmsr_free_resource(acb);
4800a1103e04SXin LI 			printf("arcmsr%d: rman_get_start failure!\n", device_get_unit(dev));
4801a1103e04SXin LI 			return ENXIO;
4802a1103e04SXin LI 		}
4803a1103e04SXin LI 		mem_base0 = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]);
4804a1103e04SXin LI 		if(mem_base0 == 0) {
4805a1103e04SXin LI 			arcmsr_free_resource(acb);
4806a1103e04SXin LI 			printf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev));
4807a1103e04SXin LI 			return ENXIO;
4808a1103e04SXin LI 		}
4809a1103e04SXin LI 		acb->btag[0] = rman_get_bustag(acb->sys_res_arcmsr[0]);
4810a1103e04SXin LI 		acb->bhandle[0] = rman_get_bushandle(acb->sys_res_arcmsr[0]);
4811a1103e04SXin LI 		acb->pmu = (struct MessageUnit_UNION *)mem_base0;
4812a1103e04SXin LI 		acb->doneq_index = 0;
4813a1103e04SXin LI 		acb->in_doorbell = 0;
4814a1103e04SXin LI 		acb->out_doorbell = 0;
4815fc5ef1caSXin LI 		acb->rid[0] = rid0;
4816a1103e04SXin LI 		CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_status, 0); /*clear interrupt*/
4817a1103e04SXin LI 		CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, ARCMSR_HBEMU_DOORBELL_SYNC); /* synchronize doorbell to 0 */
48187a7bc959SXin LI 		}
48197a7bc959SXin LI 		break;
4820fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_F: {
4821fa42a0bfSXin LI 		u_int32_t rid0 = PCIR_BAR(0);
4822fa42a0bfSXin LI 		vm_offset_t	mem_base0;
4823fa42a0bfSXin LI 		unsigned long	host_buffer_dma;
4824fa42a0bfSXin LI 
4825fa42a0bfSXin LI 		acb->sys_res_arcmsr[0] = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid0, RF_ACTIVE);
4826fa42a0bfSXin LI 		if(acb->sys_res_arcmsr[0] == NULL) {
4827fa42a0bfSXin LI 			arcmsr_free_resource(acb);
4828fa42a0bfSXin LI 			printf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev));
4829fa42a0bfSXin LI 			return ENOMEM;
4830fa42a0bfSXin LI 		}
4831fa42a0bfSXin LI 		if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) {
4832fa42a0bfSXin LI 			arcmsr_free_resource(acb);
4833fa42a0bfSXin LI 			printf("arcmsr%d: rman_get_start failure!\n", device_get_unit(dev));
4834fa42a0bfSXin LI 			return ENXIO;
4835fa42a0bfSXin LI 		}
4836fa42a0bfSXin LI 		mem_base0 = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]);
4837fa42a0bfSXin LI 		if(mem_base0 == 0) {
4838fa42a0bfSXin LI 			arcmsr_free_resource(acb);
4839fa42a0bfSXin LI 			printf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev));
4840fa42a0bfSXin LI 			return ENXIO;
4841fa42a0bfSXin LI 		}
4842fa42a0bfSXin LI 		acb->btag[0] = rman_get_bustag(acb->sys_res_arcmsr[0]);
4843fa42a0bfSXin LI 		acb->bhandle[0] = rman_get_bushandle(acb->sys_res_arcmsr[0]);
4844fa42a0bfSXin LI 		acb->pmu = (struct MessageUnit_UNION *)mem_base0;
4845fa42a0bfSXin LI 		acb->doneq_index = 0;
4846fa42a0bfSXin LI 		acb->in_doorbell = 0;
4847fa42a0bfSXin LI 		acb->out_doorbell = 0;
4848fa42a0bfSXin LI 		acb->rid[0] = rid0;
4849fa42a0bfSXin LI 		CHIP_REG_WRITE32(HBF_MessageUnit, 0, host_int_status, 0); /*clear interrupt*/
4850fa42a0bfSXin LI 		CHIP_REG_WRITE32(HBF_MessageUnit, 0, iobound_doorbell, ARCMSR_HBEMU_DOORBELL_SYNC); /* synchronize doorbell to 0 */
48516964b77eS黃清隆 		arcmsr_wait_firmware_ready(acb);
4852fa42a0bfSXin LI 		host_buffer_dma = acb->completeQ_phys + COMPLETION_Q_POOL_SIZE;
4853fa42a0bfSXin 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 */
4854fa42a0bfSXin LI 		CHIP_REG_WRITE32(HBF_MessageUnit, 0, inbound_msgaddr1, (u_int32_t)((host_buffer_dma >> 16) >> 16));/* host buffer high addr */
4855fa42a0bfSXin LI 		CHIP_REG_WRITE32(HBF_MessageUnit, 0, iobound_doorbell, ARCMSR_HBFMU_DOORBELL_SYNC1);       /* set host buffer physical address */
4856fa42a0bfSXin LI 		}
4857fa42a0bfSXin LI 		break;
485844f05562SScott Long 	}
4859ad6d6297SScott Long 	if(acb->acb_flags & ACB_F_MAPFREESRB_FAILD) {
4860ad6d6297SScott Long 		arcmsr_free_resource(acb);
486144f05562SScott Long 		printf("arcmsr%d: map free srb failure!\n", device_get_unit(dev));
4862f1c579b1SScott Long 		return ENXIO;
4863f1c579b1SScott Long 	}
4864d74001adSXin LI 	acb->acb_flags  |= (ACB_F_MESSAGE_WQBUFFER_CLEARED|ACB_F_MESSAGE_RQBUFFER_CLEARED|ACB_F_MESSAGE_WQBUFFER_READ);
4865ad6d6297SScott Long 	acb->acb_flags &= ~ACB_F_SCSISTOPADAPTER;
4866ad6d6297SScott Long 	/*
4867ad6d6297SScott Long 	********************************************************************
4868ad6d6297SScott Long 	** init raid volume state
4869ad6d6297SScott Long 	********************************************************************
4870ad6d6297SScott Long 	*/
4871ad6d6297SScott Long 	for(i=0; i < ARCMSR_MAX_TARGETID; i++) {
4872ad6d6297SScott Long 		for(j=0; j < ARCMSR_MAX_TARGETLUN; j++) {
487344f05562SScott Long 			acb->devstate[i][j] = ARECA_RAID_GONE;
4874ad6d6297SScott Long 		}
4875ad6d6297SScott Long 	}
4876ad6d6297SScott Long 	arcmsr_iop_init(acb);
4877f1c579b1SScott Long 	return(0);
4878f1c579b1SScott Long }
4879a1103e04SXin LI 
4880a1103e04SXin LI static int arcmsr_setup_msix(struct AdapterControlBlock *acb)
4881a1103e04SXin LI {
4882a1103e04SXin LI 	int i;
4883a1103e04SXin LI 
4884a1103e04SXin LI 	for (i = 0; i < acb->msix_vectors; i++) {
4885fc5ef1caSXin LI 		acb->irq_id[i] = 1 + i;
4886a1103e04SXin LI 		acb->irqres[i] = bus_alloc_resource_any(acb->pci_dev,
4887a1103e04SXin LI 		    SYS_RES_IRQ, &acb->irq_id[i], RF_ACTIVE);
4888a1103e04SXin LI 		if (acb->irqres[i] == NULL) {
4889a1103e04SXin LI 			printf("arcmsr: Can't allocate MSI-X resource\n");
4890a1103e04SXin LI 			goto irq_alloc_failed;
4891a1103e04SXin LI 		}
4892a1103e04SXin LI 		if (bus_setup_intr(acb->pci_dev, acb->irqres[i],
4893a1103e04SXin LI 		    INTR_MPSAFE | INTR_TYPE_CAM, NULL, arcmsr_intr_handler,
4894a1103e04SXin LI 		    acb, &acb->ih[i])) {
4895a1103e04SXin LI 			printf("arcmsr: Cannot set up MSI-X interrupt handler\n");
4896a1103e04SXin LI 			goto irq_alloc_failed;
4897a1103e04SXin LI 		}
4898a1103e04SXin LI 	}
4899a1103e04SXin LI 	printf("arcmsr: MSI-X INT enabled\n");
4900a1103e04SXin LI 	acb->acb_flags |= ACB_F_MSIX_ENABLED;
4901a1103e04SXin LI 	return TRUE;
4902a1103e04SXin LI 
4903a1103e04SXin LI irq_alloc_failed:
4904a1103e04SXin LI 	arcmsr_teardown_intr(acb->pci_dev, acb);
4905a1103e04SXin LI 	return FALSE;
4906a1103e04SXin LI }
4907a1103e04SXin LI 
4908f1c579b1SScott Long /*
4909f1c579b1SScott Long ************************************************************************
4910f1c579b1SScott Long ************************************************************************
4911f1c579b1SScott Long */
4912f2aa0e9fSWarner Losh static int arcmsr_attach(device_t dev)
4913f1c579b1SScott Long {
4914a9e5e04eSJohn Baldwin 	struct make_dev_args args;
4915ad6d6297SScott Long 	struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev);
4916ad6d6297SScott Long 	u_int32_t unit=device_get_unit(dev);
4917f1c579b1SScott Long 	struct ccb_setasync csa;
4918f1c579b1SScott Long 	struct cam_devq	*devq;	/* Device Queue to use for this SIM */
4919f1c579b1SScott Long 	struct resource	*irqres;
4920f1c579b1SScott Long 
4921ad6d6297SScott Long 	if(acb == NULL) {
4922ad6d6297SScott Long 		printf("arcmsr%d: cannot allocate softc\n", unit);
4923ad6d6297SScott Long 		return (ENOMEM);
4924ad6d6297SScott Long 	}
49257a7bc959SXin LI 	arcmsr_mutex_init(acb);
49261e7d660aSXin LI 	acb->pci_dev = dev;
49271e7d660aSXin LI 	acb->pci_unit = unit;
4928ad6d6297SScott Long 	if(arcmsr_initialize(dev)) {
4929ad6d6297SScott Long 		printf("arcmsr%d: initialize failure!\n", unit);
4930a1103e04SXin LI 		goto initialize_failed;
4931f1c579b1SScott Long 	}
4932f1c579b1SScott Long 	/* After setting up the adapter, map our interrupt */
4933a1103e04SXin LI 	acb->msix_vectors = ARCMSR_NUM_MSIX_VECTORS;
4934a1103e04SXin LI 	if (pci_alloc_msix(dev, &acb->msix_vectors) == 0) {
4935a1103e04SXin LI 		if (arcmsr_setup_msix(acb) == TRUE)
4936a1103e04SXin LI 			goto irqx;
4937a1103e04SXin LI 	}
4938fc5ef1caSXin LI 	acb->irq_id[0] = 0;
4939a1103e04SXin LI 	irqres = bus_alloc_resource_any(dev, SYS_RES_IRQ, &acb->irq_id[0], RF_SHAREABLE | RF_ACTIVE);
4940ad6d6297SScott Long 	if(irqres == NULL ||
4941a1103e04SXin LI 		bus_setup_intr(dev, irqres, INTR_TYPE_CAM|INTR_ENTROPY|INTR_MPSAFE, NULL, arcmsr_intr_handler, acb, &acb->ih[0])) {
4942f1c579b1SScott Long 		printf("arcmsr%d: unable to register interrupt handler!\n", unit);
4943a1103e04SXin LI 		goto setup_intr_failed;
4944f1c579b1SScott Long 	}
4945a1103e04SXin LI 	acb->irqres[0] = irqres;
4946a1103e04SXin LI irqx:
4947f1c579b1SScott Long 	/*
4948f1c579b1SScott Long 	 * Now let the CAM generic SCSI layer find the SCSI devices on
4949f1c579b1SScott Long 	 * the bus *  start queue to reset to the idle loop. *
4950f1c579b1SScott Long 	 * Create device queue of SIM(s) *  (MAX_START_JOB - 1) :
4951f1c579b1SScott Long 	 * max_sim_transactions
4952f1c579b1SScott Long 	*/
4953224a78aeSXin LI 	devq = cam_simq_alloc(acb->maxOutstanding);
4954ad6d6297SScott Long 	if(devq == NULL) {
4955ad6d6297SScott Long 		printf("arcmsr%d: cam_simq_alloc failure!\n", unit);
4956a1103e04SXin LI 		goto simq_alloc_failed;
4957f1c579b1SScott Long 	}
49587a7bc959SXin LI 	acb->psim = cam_sim_alloc(arcmsr_action, arcmsr_poll, "arcmsr", acb, unit, &acb->isr_lock, 1, ARCMSR_MAX_OUTSTANDING_CMD, devq);
4959ad6d6297SScott Long 	if(acb->psim == NULL) {
4960ad6d6297SScott Long 		printf("arcmsr%d: cam_sim_alloc failure!\n", unit);
4961a1103e04SXin LI 		goto sim_alloc_failed;
4962f1c579b1SScott Long 	}
49637a7bc959SXin LI 	ARCMSR_LOCK_ACQUIRE(&acb->isr_lock);
4964b50569b7SScott Long 	if(xpt_bus_register(acb->psim, dev, 0) != CAM_SUCCESS) {
4965ad6d6297SScott Long 		printf("arcmsr%d: xpt_bus_register failure!\n", unit);
4966a1103e04SXin LI 		goto xpt_bus_failed;
4967f1c579b1SScott Long 	}
4968d74001adSXin LI 	if(xpt_create_path(&acb->ppath, /* periph */ NULL, cam_sim_path(acb->psim), CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
4969ad6d6297SScott Long 		printf("arcmsr%d: xpt_create_path failure!\n", unit);
4970a1103e04SXin LI 		goto xpt_path_failed;
4971f1c579b1SScott Long 	}
4972f1c579b1SScott Long 	/*
4973f1c579b1SScott Long 	****************************************************
4974f1c579b1SScott Long 	*/
497545f57ce1SEdward Tomasz Napierala 	memset(&csa, 0, sizeof(csa));
4976ad6d6297SScott Long 	xpt_setup_ccb(&csa.ccb_h, acb->ppath, /*priority*/5);
4977f1c579b1SScott Long 	csa.ccb_h.func_code = XPT_SASYNC_CB;
4978f1c579b1SScott Long 	csa.event_enable = AC_FOUND_DEVICE|AC_LOST_DEVICE;
4979f1c579b1SScott Long 	csa.callback = arcmsr_async;
4980ad6d6297SScott Long 	csa.callback_arg = acb->psim;
4981f1c579b1SScott Long 	xpt_action((union ccb *)&csa);
49827a7bc959SXin LI 	ARCMSR_LOCK_RELEASE(&acb->isr_lock);
4983f1c579b1SScott Long 	/* Create the control device.  */
4984a9e5e04eSJohn Baldwin 	make_dev_args_init(&args);
4985a9e5e04eSJohn Baldwin 	args.mda_devsw = &arcmsr_cdevsw;
4986a9e5e04eSJohn Baldwin 	args.mda_uid = UID_ROOT;
4987a9e5e04eSJohn Baldwin 	args.mda_gid = GID_WHEEL /* GID_OPERATOR */;
4988a9e5e04eSJohn Baldwin 	args.mda_mode = S_IRUSR | S_IWUSR;
4989a9e5e04eSJohn Baldwin 	args.mda_si_drv1 = acb;
4990a9e5e04eSJohn Baldwin 	(void)make_dev_s(&args, &acb->ioctl_dev, "arcmsr%d", unit);
4991d74001adSXin LI 
4992ad6d6297SScott Long 	(void)make_dev_alias(acb->ioctl_dev, "arc%d", unit);
499322f2616bSXin LI 	arcmsr_callout_init(&acb->devmap_callout);
4994d74001adSXin LI 	callout_reset(&acb->devmap_callout, 60 * hz, arcmsr_polling_devmap, acb);
4995dac36688SXin LI 	return (0);
4996a1103e04SXin LI xpt_path_failed:
4997a1103e04SXin LI 	xpt_bus_deregister(cam_sim_path(acb->psim));
4998a1103e04SXin LI xpt_bus_failed:
4999a1103e04SXin LI 	cam_sim_free(acb->psim, /* free_simq */ TRUE);
5000a1103e04SXin LI sim_alloc_failed:
5001a1103e04SXin LI 	cam_simq_free(devq);
5002a1103e04SXin LI simq_alloc_failed:
5003a1103e04SXin LI 	arcmsr_teardown_intr(dev, acb);
5004a1103e04SXin LI setup_intr_failed:
5005a1103e04SXin LI 	arcmsr_free_resource(acb);
5006a1103e04SXin LI initialize_failed:
5007a1103e04SXin LI 	arcmsr_mutex_destroy(acb);
5008a1103e04SXin LI 	return ENXIO;
5009f1c579b1SScott Long }
501022f2616bSXin LI 
5011f1c579b1SScott Long /*
5012f1c579b1SScott Long ************************************************************************
5013f1c579b1SScott Long ************************************************************************
5014f1c579b1SScott Long */
5015f2aa0e9fSWarner Losh static int arcmsr_probe(device_t dev)
5016f1c579b1SScott Long {
5017ad6d6297SScott Long 	u_int32_t id;
5018224a78aeSXin LI 	u_int16_t sub_device_id;
5019ad6d6297SScott Long 	static char buf[256];
50201e7d660aSXin LI 	char x_type[]={"unknown"};
5021ad6d6297SScott Long 	char *type;
5022ad6d6297SScott Long 	int raid6 = 1;
5023ad6d6297SScott Long 
5024ad6d6297SScott Long 	if (pci_get_vendor(dev) != PCI_VENDOR_ID_ARECA) {
5025ad6d6297SScott Long 		return (ENXIO);
5026ad6d6297SScott Long 	}
5027224a78aeSXin LI 	sub_device_id = pci_read_config(dev, PCIR_SUBDEV_0, 2);
5028ad6d6297SScott Long 	switch(id = pci_get_devid(dev)) {
5029f1c579b1SScott Long 	case PCIDevVenIDARC1110:
5030231c8b71SXin LI 	case PCIDevVenIDARC1200:
503144f05562SScott Long 	case PCIDevVenIDARC1201:
5032231c8b71SXin LI 	case PCIDevVenIDARC1210:
5033ad6d6297SScott Long 		raid6 = 0;
5034ad6d6297SScott Long 		/*FALLTHRU*/
5035ad6d6297SScott Long 	case PCIDevVenIDARC1120:
5036ad6d6297SScott Long 	case PCIDevVenIDARC1130:
5037ad6d6297SScott Long 	case PCIDevVenIDARC1160:
5038ad6d6297SScott Long 	case PCIDevVenIDARC1170:
5039f1c579b1SScott Long 	case PCIDevVenIDARC1220:
5040f1c579b1SScott Long 	case PCIDevVenIDARC1230:
5041231c8b71SXin LI 	case PCIDevVenIDARC1231:
5042f1c579b1SScott Long 	case PCIDevVenIDARC1260:
5043231c8b71SXin LI 	case PCIDevVenIDARC1261:
5044ad6d6297SScott Long 	case PCIDevVenIDARC1270:
5045ad6d6297SScott Long 	case PCIDevVenIDARC1280:
50467a7bc959SXin LI 		type = "SATA 3G";
5047ad6d6297SScott Long 		break;
5048d74001adSXin LI 	case PCIDevVenIDARC1212:
5049d74001adSXin LI 	case PCIDevVenIDARC1222:
5050ad6d6297SScott Long 	case PCIDevVenIDARC1380:
5051ad6d6297SScott Long 	case PCIDevVenIDARC1381:
5052ad6d6297SScott Long 	case PCIDevVenIDARC1680:
5053ad6d6297SScott Long 	case PCIDevVenIDARC1681:
5054d74001adSXin LI 		type = "SAS 3G";
5055d74001adSXin LI 		break;
5056d74001adSXin LI 	case PCIDevVenIDARC1880:
5057dac36688SXin LI 	case PCIDevVenIDARC1882:
5058dac36688SXin LI 	case PCIDevVenIDARC1213:
5059dac36688SXin LI 	case PCIDevVenIDARC1223:
5060fc5ef1caSXin LI 		if ((sub_device_id == ARECA_SUB_DEV_ID_1883) ||
5061fc5ef1caSXin LI 		    (sub_device_id == ARECA_SUB_DEV_ID_1216) ||
5062fc5ef1caSXin LI 		    (sub_device_id == ARECA_SUB_DEV_ID_1226))
5063224a78aeSXin LI 			type = "SAS 12G";
5064224a78aeSXin LI 		else
5065d74001adSXin LI 			type = "SAS 6G";
5066ad6d6297SScott Long 		break;
5067a1103e04SXin LI 	case PCIDevVenIDARC1884:
5068a1103e04SXin LI 		type = "SAS 12G";
5069a1103e04SXin LI 		break;
5070fa42a0bfSXin LI 	case PCIDevVenIDARC1886_:
5071fa42a0bfSXin LI 	case PCIDevVenIDARC1886:
5072fa42a0bfSXin LI 		type = "NVME,SAS-12G,SATA-6G";
5073fa42a0bfSXin LI 		break;
50747a7bc959SXin LI 	case PCIDevVenIDARC1214:
5075b23a1998SXin LI 	case PCIDevVenIDARC1203:
50767a7bc959SXin LI 		type = "SATA 6G";
50777a7bc959SXin LI 		break;
5078ad6d6297SScott Long 	default:
5079231c8b71SXin LI 		type = x_type;
50801e7d660aSXin LI 		raid6 = 0;
5081ad6d6297SScott Long 		break;
5082f1c579b1SScott Long 	}
5083231c8b71SXin LI 	if(type == x_type)
5084231c8b71SXin LI 		return(ENXIO);
50851e7d660aSXin LI 	sprintf(buf, "Areca %s Host Adapter RAID Controller %s\n%s\n",
50861e7d660aSXin LI 		type, raid6 ? "(RAID6 capable)" : "", ARCMSR_DRIVER_VERSION);
5087ad6d6297SScott Long 	device_set_desc_copy(dev, buf);
508803389298SXin LI 	return (BUS_PROBE_DEFAULT);
5089f1c579b1SScott Long }
5090f1c579b1SScott Long /*
5091f1c579b1SScott Long ************************************************************************
5092f1c579b1SScott Long ************************************************************************
5093f1c579b1SScott Long */
5094f2aa0e9fSWarner Losh static int arcmsr_shutdown(device_t dev)
5095f1c579b1SScott Long {
509644f05562SScott Long 	u_int32_t  i;
5097ad6d6297SScott Long 	struct CommandControlBlock *srb;
5098ad6d6297SScott Long 	struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev);
5099f1c579b1SScott Long 
5100f1c579b1SScott Long 	/* stop adapter background rebuild */
51017a7bc959SXin LI 	ARCMSR_LOCK_ACQUIRE(&acb->isr_lock);
510244f05562SScott Long 	/* disable all outbound interrupt */
5103bca8e8c0SScott Long 	arcmsr_disable_allintr(acb);
5104ad6d6297SScott Long 	arcmsr_stop_adapter_bgrb(acb);
5105ad6d6297SScott Long 	arcmsr_flush_adapter_cache(acb);
5106f1c579b1SScott Long 	/* abort all outstanding command */
5107ad6d6297SScott Long 	acb->acb_flags |= ACB_F_SCSISTOPADAPTER;
5108ad6d6297SScott Long 	acb->acb_flags &= ~ACB_F_IOP_INITED;
5109ad6d6297SScott Long 	if(acb->srboutstandingcount != 0) {
511044f05562SScott Long 		/*clear and abort all outbound posted Q*/
511144f05562SScott Long 		arcmsr_done4abort_postqueue(acb);
511244f05562SScott Long 		/* talk to iop 331 outstanding command aborted*/
5113ad6d6297SScott Long 		arcmsr_abort_allcmd(acb);
5114ad6d6297SScott Long 		for(i=0; i < ARCMSR_MAX_FREESRB_NUM; i++) {
5115ad6d6297SScott Long 			srb = acb->psrb_pool[i];
511622f2616bSXin LI 			if(srb->srb_state == ARCMSR_SRB_START) {
511722f2616bSXin LI 				srb->srb_state = ARCMSR_SRB_ABORTED;
5118ad6d6297SScott Long 				srb->pccb->ccb_h.status |= CAM_REQ_ABORTED;
5119ad6d6297SScott Long 				arcmsr_srb_complete(srb, 1);
5120f1c579b1SScott Long 			}
5121f1c579b1SScott Long 		}
5122f1c579b1SScott Long 	}
512322f2616bSXin LI 	acb->srboutstandingcount = 0;
5124ad6d6297SScott Long 	acb->workingsrb_doneindex = 0;
5125ad6d6297SScott Long 	acb->workingsrb_startindex = 0;
512622f2616bSXin LI 	acb->pktRequestCount = 0;
512722f2616bSXin LI 	acb->pktReturnCount = 0;
51287a7bc959SXin LI 	ARCMSR_LOCK_RELEASE(&acb->isr_lock);
5129f2aa0e9fSWarner Losh 	return (0);
5130f1c579b1SScott Long }
5131f1c579b1SScott Long /*
5132f1c579b1SScott Long ************************************************************************
5133f1c579b1SScott Long ************************************************************************
5134f1c579b1SScott Long */
5135fc5ef1caSXin LI static void arcmsr_teardown_intr(device_t dev, struct AdapterControlBlock *acb)
5136a1103e04SXin LI {
5137a1103e04SXin LI 	int i;
5138a1103e04SXin LI 
5139a1103e04SXin LI 	if (acb->acb_flags & ACB_F_MSIX_ENABLED) {
5140a1103e04SXin LI 		for (i = 0; i < acb->msix_vectors; i++) {
5141a1103e04SXin LI 			if (acb->ih[i])
5142a1103e04SXin LI 				bus_teardown_intr(dev, acb->irqres[i], acb->ih[i]);
5143a1103e04SXin LI 			if (acb->irqres[i] != NULL)
5144a1103e04SXin LI 				bus_release_resource(dev, SYS_RES_IRQ,
5145a1103e04SXin LI 				    acb->irq_id[i], acb->irqres[i]);
5146a1103e04SXin LI 
5147a1103e04SXin LI 			acb->ih[i] = NULL;
5148a1103e04SXin LI 		}
5149a1103e04SXin LI 		pci_release_msi(dev);
5150a1103e04SXin LI 	} else {
5151a1103e04SXin LI 		if (acb->ih[0])
5152a1103e04SXin LI 			bus_teardown_intr(dev, acb->irqres[0], acb->ih[0]);
5153a1103e04SXin LI 		if (acb->irqres[0] != NULL)
5154a1103e04SXin LI 			bus_release_resource(dev, SYS_RES_IRQ,
5155a1103e04SXin LI 			    acb->irq_id[0], acb->irqres[0]);
5156a1103e04SXin LI 		acb->ih[0] = NULL;
5157a1103e04SXin LI 	}
5158a1103e04SXin LI 
5159a1103e04SXin LI }
5160a1103e04SXin LI /*
5161a1103e04SXin LI ************************************************************************
5162a1103e04SXin LI ************************************************************************
5163a1103e04SXin LI */
5164f2aa0e9fSWarner Losh static int arcmsr_detach(device_t dev)
5165f1c579b1SScott Long {
5166ad6d6297SScott Long 	struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev);
516744f05562SScott Long 	int i;
5168f1c579b1SScott Long 
5169d74001adSXin LI 	callout_stop(&acb->devmap_callout);
5170a1103e04SXin LI 	arcmsr_teardown_intr(dev, acb);
5171f1c579b1SScott Long 	arcmsr_shutdown(dev);
5172ad6d6297SScott Long 	arcmsr_free_resource(acb);
517344f05562SScott Long 	for(i=0; (acb->sys_res_arcmsr[i]!=NULL) && (i<2); i++) {
5174fc5ef1caSXin LI 		bus_release_resource(dev, SYS_RES_MEMORY, acb->rid[i], acb->sys_res_arcmsr[i]);
517544f05562SScott Long 	}
51767a7bc959SXin LI 	ARCMSR_LOCK_ACQUIRE(&acb->isr_lock);
5177ad6d6297SScott Long 	xpt_async(AC_LOST_DEVICE, acb->ppath, NULL);
5178ad6d6297SScott Long 	xpt_free_path(acb->ppath);
5179ad6d6297SScott Long 	xpt_bus_deregister(cam_sim_path(acb->psim));
5180ad6d6297SScott Long 	cam_sim_free(acb->psim, TRUE);
51817a7bc959SXin LI 	ARCMSR_LOCK_RELEASE(&acb->isr_lock);
51827a7bc959SXin LI 	arcmsr_mutex_destroy(acb);
5183f1c579b1SScott Long 	return (0);
5184f1c579b1SScott Long }
5185f1c579b1SScott Long 
518622f2616bSXin LI #ifdef ARCMSR_DEBUG1
518722f2616bSXin LI static void arcmsr_dump_data(struct AdapterControlBlock *acb)
518822f2616bSXin LI {
518922f2616bSXin LI 	if((acb->pktRequestCount - acb->pktReturnCount) == 0)
519022f2616bSXin LI 		return;
519122f2616bSXin LI 	printf("Command Request Count   =0x%x\n",acb->pktRequestCount);
519222f2616bSXin LI 	printf("Command Return Count    =0x%x\n",acb->pktReturnCount);
519322f2616bSXin LI 	printf("Command (Req-Rtn) Count =0x%x\n",(acb->pktRequestCount - acb->pktReturnCount));
519422f2616bSXin LI 	printf("Queued Command Count    =0x%x\n",acb->srboutstandingcount);
519522f2616bSXin LI }
519622f2616bSXin LI #endif
5197