xref: /freebsd/sys/dev/arcmsr/arcmsr.c (revision d74001ad8d82395f9d0d24b0f05ddcc51986427d)
1f1c579b1SScott Long /*
246a7789eSMatt Jacob *****************************************************************************************
3f1c579b1SScott Long **        O.S   : FreeBSD
4f1c579b1SScott Long **   FILE NAME  : arcmsr.c
5*d74001adSXin LI **        BY    : Erich Chen, Ching Huang
6f1c579b1SScott Long **   Description: SCSI RAID Device Driver for
7*d74001adSXin LI **                ARECA (ARC11XX/ARC12XX/ARC13XX/ARC16XX/ARC188x) SATA/SAS RAID HOST Adapter
8ad6d6297SScott Long **                ARCMSR RAID Host adapter
9ad6d6297SScott Long **                [RAID controller:INTEL 331(PCI-X) 341(PCI-EXPRESS) chip set]
10f1c579b1SScott Long ******************************************************************************************
11f1c579b1SScott Long ************************************************************************
12f1c579b1SScott Long **
13*d74001adSXin LI ** Copyright (c) 2004-2010 ARECA Co. Ltd.
14f1c579b1SScott Long **        Erich Chen, Taipei Taiwan 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.
37f1c579b1SScott Long **************************************************************************
38f1c579b1SScott Long ** History
39f1c579b1SScott Long **
40f1c579b1SScott Long **        REV#         DATE	            NAME	         DESCRIPTION
41f1c579b1SScott Long **     1.00.00.00    3/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
43ad6d6297SScott Long **     1.20.00.03    4/19/2005         Erich Chen        add SATA 24 Ports adapter type support
44ad6d6297SScott Long **                                                       clean unused function
45ad6d6297SScott Long **     1.20.00.12    9/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
50ad6d6297SScott Long **     1.20.00.13    8/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
60*d74001adSXin LI **     1.20.00.17   07/15/2010         Ching Huang       Added support ARC1880
61*d74001adSXin LI **							 report CAM_DEV_NOT_THERE instead of CAM_SEL_TIMEOUT when device failed,
62*d74001adSXin LI **							 prevent cam_periph_error removing all LUN devices of one Target id
63*d74001adSXin LI **							 for any one LUN device failed
64f1c579b1SScott Long ******************************************************************************************
65ad6d6297SScott Long * $FreeBSD$
66f1c579b1SScott Long */
67f1c579b1SScott Long #include <sys/param.h>
68f1c579b1SScott Long #include <sys/systm.h>
69f1c579b1SScott Long #include <sys/malloc.h>
70f1c579b1SScott Long #include <sys/kernel.h>
71f1c579b1SScott Long #include <sys/bus.h>
72f1c579b1SScott Long #include <sys/queue.h>
73f1c579b1SScott Long #include <sys/stat.h>
74f1c579b1SScott Long #include <sys/devicestat.h>
75f1c579b1SScott Long #include <sys/kthread.h>
76f1c579b1SScott Long #include <sys/module.h>
77f1c579b1SScott Long #include <sys/proc.h>
78f1c579b1SScott Long #include <sys/lock.h>
79f1c579b1SScott Long #include <sys/sysctl.h>
80f1c579b1SScott Long #include <sys/poll.h>
81f1c579b1SScott Long #include <sys/ioccom.h>
82f1c579b1SScott Long #include <vm/vm.h>
83f1c579b1SScott Long #include <vm/vm_param.h>
84f1c579b1SScott Long #include <vm/pmap.h>
85f1c579b1SScott Long 
86f1c579b1SScott Long #include <isa/rtc.h>
87f1c579b1SScott Long 
88f1c579b1SScott Long #include <machine/bus.h>
89f1c579b1SScott Long #include <machine/resource.h>
90f1c579b1SScott Long #include <machine/atomic.h>
91f1c579b1SScott Long #include <sys/conf.h>
92f1c579b1SScott Long #include <sys/rman.h>
93f1c579b1SScott Long 
94f1c579b1SScott Long #include <cam/cam.h>
95f1c579b1SScott Long #include <cam/cam_ccb.h>
96f1c579b1SScott Long #include <cam/cam_sim.h>
97*d74001adSXin LI #include <cam/cam_periph.h>
98*d74001adSXin LI #include <cam/cam_xpt_periph.h>
99f1c579b1SScott Long #include <cam/cam_xpt_sim.h>
100f1c579b1SScott Long #include <cam/cam_debug.h>
101f1c579b1SScott Long #include <cam/scsi/scsi_all.h>
102f1c579b1SScott Long #include <cam/scsi/scsi_message.h>
103f1c579b1SScott Long /*
104f1c579b1SScott Long **************************************************************************
105f1c579b1SScott Long **************************************************************************
106f1c579b1SScott Long */
107f1c579b1SScott Long #if __FreeBSD_version >= 500005
108f1c579b1SScott Long     #include <sys/selinfo.h>
109f1c579b1SScott Long     #include <sys/mutex.h>
110ad6d6297SScott Long     #include <sys/endian.h>
111f1c579b1SScott Long     #include <dev/pci/pcivar.h>
112f1c579b1SScott Long     #include <dev/pci/pcireg.h>
113579ec1a5SScott Long     #define ARCMSR_LOCK_INIT(l, s)	mtx_init(l, s, NULL, MTX_DEF)
1145878cbecSScott Long     #define ARCMSR_LOCK_DESTROY(l)	mtx_destroy(l)
115f1c579b1SScott Long     #define ARCMSR_LOCK_ACQUIRE(l)	mtx_lock(l)
116f1c579b1SScott Long     #define ARCMSR_LOCK_RELEASE(l)	mtx_unlock(l)
117ad6d6297SScott Long     #define ARCMSR_LOCK_TRY(l)		mtx_trylock(l)
118ad6d6297SScott Long     #define arcmsr_htole32(x)		htole32(x)
119f1c579b1SScott Long     typedef struct mtx		arcmsr_lock_t;
120f1c579b1SScott Long #else
121f1c579b1SScott Long     #include <sys/select.h>
122f1c579b1SScott Long     #include <pci/pcivar.h>
123f1c579b1SScott Long     #include <pci/pcireg.h>
124f1c579b1SScott Long     #define ARCMSR_LOCK_INIT(l, s)	simple_lock_init(l)
1255878cbecSScott Long     #define ARCMSR_LOCK_DESTROY(l)
126f1c579b1SScott Long     #define ARCMSR_LOCK_ACQUIRE(l)	simple_lock(l)
127f1c579b1SScott Long     #define ARCMSR_LOCK_RELEASE(l)	simple_unlock(l)
128ad6d6297SScott Long     #define ARCMSR_LOCK_TRY(l)		simple_lock_try(l)
129ad6d6297SScott Long     #define arcmsr_htole32(x)		(x)
130f1c579b1SScott Long     typedef struct simplelock		arcmsr_lock_t;
131f1c579b1SScott Long #endif
13244f05562SScott Long 
13344f05562SScott Long #if !defined(CAM_NEW_TRAN_CODE) && __FreeBSD_version >= 700025
13444f05562SScott Long #define	CAM_NEW_TRAN_CODE	1
13544f05562SScott Long #endif
13644f05562SScott Long 
137f1c579b1SScott Long #include <dev/arcmsr/arcmsr.h>
13844f05562SScott Long #define ARCMSR_SRBS_POOL_SIZE           ((sizeof(struct CommandControlBlock) * ARCMSR_MAX_FREESRB_NUM))
139f1c579b1SScott Long /*
140f1c579b1SScott Long **************************************************************************
141f1c579b1SScott Long **************************************************************************
142f1c579b1SScott Long */
14344f05562SScott Long #define CHIP_REG_READ32(s, b, r)	bus_space_read_4(acb->btag[b], acb->bhandle[b], offsetof(struct s, r))
14444f05562SScott Long #define CHIP_REG_WRITE32(s, b, r, d)	bus_space_write_4(acb->btag[b], acb->bhandle[b], offsetof(struct s, r), d)
145f1c579b1SScott Long /*
146f1c579b1SScott Long **************************************************************************
147f1c579b1SScott Long **************************************************************************
148f1c579b1SScott Long */
149ad6d6297SScott Long static struct CommandControlBlock * arcmsr_get_freesrb(struct AdapterControlBlock *acb);
150ad6d6297SScott Long static u_int8_t arcmsr_seek_cmd2abort(union ccb * abortccb);
151f2aa0e9fSWarner Losh static int arcmsr_probe(device_t dev);
152f2aa0e9fSWarner Losh static int arcmsr_attach(device_t dev);
153f2aa0e9fSWarner Losh static int arcmsr_detach(device_t dev);
154ad6d6297SScott Long static u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t ioctl_cmd, caddr_t arg);
155ad6d6297SScott Long static void arcmsr_iop_parking(struct AdapterControlBlock *acb);
156f2aa0e9fSWarner Losh static int arcmsr_shutdown(device_t dev);
15744f05562SScott Long static void arcmsr_interrupt(struct AdapterControlBlock *acb);
158ad6d6297SScott Long static void arcmsr_polling_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb);
159ad6d6297SScott Long static void arcmsr_free_resource(struct AdapterControlBlock *acb);
160ad6d6297SScott Long static void arcmsr_bus_reset(struct AdapterControlBlock *acb);
161ad6d6297SScott Long static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb);
162ad6d6297SScott Long static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb);
163ad6d6297SScott Long static void arcmsr_iop_init(struct AdapterControlBlock *acb);
164ad6d6297SScott Long static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb);
16544f05562SScott Long static void arcmsr_post_ioctldata2iop(struct AdapterControlBlock *acb);
166ad6d6297SScott Long static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb);
167ad6d6297SScott Long static void arcmsr_srb_complete(struct CommandControlBlock *srb, int stand_flag);
168ad6d6297SScott Long static void arcmsr_iop_reset(struct AdapterControlBlock *acb);
169ad6d6297SScott Long static void arcmsr_report_sense_info(struct CommandControlBlock *srb);
170ad6d6297SScott Long static void arcmsr_build_srb(struct CommandControlBlock *srb, bus_dma_segment_t * dm_segs, u_int32_t nseg);
171ad6d6297SScott Long static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb * pccb);
172ad6d6297SScott Long static int arcmsr_resume(device_t dev);
173ad6d6297SScott Long static int arcmsr_suspend(device_t dev);
174*d74001adSXin LI static void arcmsr_rescanLun_cb(struct cam_periph *periph, union ccb *ccb);
175*d74001adSXin LI static void	arcmsr_polling_devmap(void* arg);
176f1c579b1SScott Long /*
177f1c579b1SScott Long **************************************************************************
178ad6d6297SScott Long **************************************************************************
179ad6d6297SScott Long */
180ad6d6297SScott Long static void UDELAY(u_int32_t us) { DELAY(us); }
181ad6d6297SScott Long /*
182ad6d6297SScott Long **************************************************************************
183f1c579b1SScott Long **************************************************************************
184f1c579b1SScott Long */
185f1c579b1SScott Long static bus_dmamap_callback_t arcmsr_map_freesrb;
186f1c579b1SScott Long static bus_dmamap_callback_t arcmsr_executesrb;
187f1c579b1SScott Long /*
188f1c579b1SScott Long **************************************************************************
189f1c579b1SScott Long **************************************************************************
190f1c579b1SScott Long */
191f1c579b1SScott Long static d_open_t	arcmsr_open;
192f1c579b1SScott Long static d_close_t arcmsr_close;
193f1c579b1SScott Long static d_ioctl_t arcmsr_ioctl;
194f1c579b1SScott Long 
195f1c579b1SScott Long static device_method_t arcmsr_methods[]={
196f1c579b1SScott Long 	DEVMETHOD(device_probe,		arcmsr_probe),
197f1c579b1SScott Long 	DEVMETHOD(device_attach,	arcmsr_attach),
198f1c579b1SScott Long 	DEVMETHOD(device_detach,	arcmsr_detach),
199f1c579b1SScott Long 	DEVMETHOD(device_shutdown,	arcmsr_shutdown),
200ad6d6297SScott Long 	DEVMETHOD(device_suspend,	arcmsr_suspend),
201ad6d6297SScott Long 	DEVMETHOD(device_resume,	arcmsr_resume),
202ad6d6297SScott Long 	DEVMETHOD(bus_print_child,	bus_generic_print_child),
203ad6d6297SScott Long 	DEVMETHOD(bus_driver_added, 	bus_generic_driver_added),
204f1c579b1SScott Long 	{ 0, 0 }
205f1c579b1SScott Long };
206f1c579b1SScott Long 
207f1c579b1SScott Long static driver_t arcmsr_driver={
208ad6d6297SScott Long 	"arcmsr", arcmsr_methods, sizeof(struct AdapterControlBlock)
209f1c579b1SScott Long };
210f1c579b1SScott Long 
211f1c579b1SScott Long static devclass_t arcmsr_devclass;
212f1c579b1SScott Long DRIVER_MODULE(arcmsr, pci, arcmsr_driver, arcmsr_devclass, 0, 0);
213d3cf342dSScott Long MODULE_DEPEND(arcmsr, pci, 1, 1, 1);
214d3cf342dSScott Long MODULE_DEPEND(arcmsr, cam, 1, 1, 1);
215ad6d6297SScott Long #ifndef BUS_DMA_COHERENT
216ad6d6297SScott Long 	#define	BUS_DMA_COHERENT	0x04	/* hint: map memory in a coherent way */
217ad6d6297SScott Long #endif
218ad6d6297SScott Long #if __FreeBSD_version >= 501000
219ad6d6297SScott Long 	#ifndef D_NEEDGIANT
220ad6d6297SScott Long 		#define D_NEEDGIANT	0x00400000	/* driver want Giant */
221ad6d6297SScott Long 	#endif
222ad6d6297SScott Long 	#ifndef D_VERSION
223ad6d6297SScott Long 		#define D_VERSION	0x20011966
224ad6d6297SScott Long 	#endif
225f1c579b1SScott Long static struct cdevsw arcmsr_cdevsw={
226ad6d6297SScott Long 	#if __FreeBSD_version > 502010
227f1c579b1SScott Long 		.d_version = D_VERSION,
228ad6d6297SScott Long 	#endif
229f1c579b1SScott Long 	.d_flags   = D_NEEDGIANT,
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 	};
235f1c579b1SScott Long #else
236f1c579b1SScott Long 	#define ARCMSR_CDEV_MAJOR	180
237f1c579b1SScott Long 
238f1c579b1SScott Long static struct cdevsw arcmsr_cdevsw = {
239f1c579b1SScott Long 		arcmsr_open, 		        /* open     */
240f1c579b1SScott Long 		arcmsr_close, 		        /* close    */
241f1c579b1SScott Long 		noread, 		        /* read     */
242f1c579b1SScott Long 		nowrite, 		        /* write    */
243f1c579b1SScott Long 		arcmsr_ioctl, 		        /* ioctl    */
244f1c579b1SScott Long 		nopoll, 		        /* poll     */
245f1c579b1SScott Long 		nommap, 		        /* mmap     */
246f1c579b1SScott Long 		nostrategy, 		        /* strategy */
247f1c579b1SScott Long 		"arcmsr", 		        /* name     */
248f1c579b1SScott Long 		ARCMSR_CDEV_MAJOR, 		/* major    */
249f1c579b1SScott Long 		nodump, 			/* dump     */
250f1c579b1SScott Long 		nopsize, 			/* psize    */
251f1c579b1SScott Long 		0				/* flags    */
252f1c579b1SScott Long 	};
253f1c579b1SScott Long #endif
254*d74001adSXin LI /*
255*d74001adSXin LI **************************************************************************
256*d74001adSXin LI **************************************************************************
257*d74001adSXin LI */
258f1c579b1SScott Long #if __FreeBSD_version < 500005
259f1c579b1SScott Long 	static int arcmsr_open(dev_t dev, int flags, int fmt, struct proc *proc)
260f1c579b1SScott Long #else
261f1c579b1SScott Long 	#if __FreeBSD_version < 503000
262f1c579b1SScott Long 		static int arcmsr_open(dev_t dev, int flags, int fmt, struct thread *proc)
263f1c579b1SScott Long 	#else
26400b4e54aSWarner Losh 		static int arcmsr_open(struct cdev *dev, int flags, int fmt, struct thread *proc)
265f1c579b1SScott Long 	#endif
266f1c579b1SScott Long #endif
267f1c579b1SScott Long {
268f1c579b1SScott Long 	#if __FreeBSD_version < 503000
269ad6d6297SScott Long 		struct AdapterControlBlock *acb=dev->si_drv1;
270f1c579b1SScott Long 	#else
2716bfa9a2dSEd Schouten 		int	unit = dev2unit(dev);
272ad6d6297SScott Long 		struct AdapterControlBlock *acb = devclass_get_softc(arcmsr_devclass, unit);
273f1c579b1SScott Long 	#endif
274ad6d6297SScott Long 	if(acb==NULL) {
275f1c579b1SScott Long 		return ENXIO;
276f1c579b1SScott Long 	}
277f1c579b1SScott Long 	return 0;
278f1c579b1SScott Long }
279f1c579b1SScott Long /*
280f1c579b1SScott Long **************************************************************************
281f1c579b1SScott Long **************************************************************************
282f1c579b1SScott Long */
283f1c579b1SScott Long #if __FreeBSD_version < 500005
284f1c579b1SScott Long 	static int arcmsr_close(dev_t dev, int flags, int fmt, struct proc *proc)
285f1c579b1SScott Long #else
286f1c579b1SScott Long 	#if __FreeBSD_version < 503000
287f1c579b1SScott Long 		static int arcmsr_close(dev_t dev, int flags, int fmt, struct thread *proc)
288f1c579b1SScott Long 	#else
28900b4e54aSWarner Losh 		static int arcmsr_close(struct cdev *dev, int flags, int fmt, struct thread *proc)
290f1c579b1SScott Long 	#endif
291f1c579b1SScott Long #endif
292f1c579b1SScott Long {
293f1c579b1SScott Long 	#if __FreeBSD_version < 503000
294ad6d6297SScott Long 		struct AdapterControlBlock *acb=dev->si_drv1;
295f1c579b1SScott Long 	#else
2966bfa9a2dSEd Schouten 		int	unit = dev2unit(dev);
297ad6d6297SScott Long 		struct AdapterControlBlock *acb = devclass_get_softc(arcmsr_devclass, unit);
298f1c579b1SScott Long 	#endif
299ad6d6297SScott Long 	if(acb==NULL) {
300f1c579b1SScott Long 		return ENXIO;
301f1c579b1SScott Long 	}
302f1c579b1SScott Long 	return 0;
303f1c579b1SScott Long }
304f1c579b1SScott Long /*
305f1c579b1SScott Long **************************************************************************
306f1c579b1SScott Long **************************************************************************
307f1c579b1SScott Long */
308f1c579b1SScott Long #if __FreeBSD_version < 500005
309f1c579b1SScott Long 	static int arcmsr_ioctl(dev_t dev, u_long ioctl_cmd, caddr_t arg, int flags, struct proc *proc)
310f1c579b1SScott Long #else
311f1c579b1SScott Long 	#if __FreeBSD_version < 503000
312f1c579b1SScott Long 		static int arcmsr_ioctl(dev_t dev, u_long ioctl_cmd, caddr_t arg, int flags, struct thread *proc)
313f1c579b1SScott Long 	#else
31400b4e54aSWarner Losh 		static int arcmsr_ioctl(struct cdev *dev, u_long ioctl_cmd, caddr_t arg, int flags, struct thread *proc)
315f1c579b1SScott Long 	#endif
316f1c579b1SScott Long #endif
317f1c579b1SScott Long {
318f1c579b1SScott Long 	#if __FreeBSD_version < 503000
319ad6d6297SScott Long 		struct AdapterControlBlock *acb=dev->si_drv1;
320f1c579b1SScott Long 	#else
3216bfa9a2dSEd Schouten 		int	unit = dev2unit(dev);
322ad6d6297SScott Long 		struct AdapterControlBlock *acb = devclass_get_softc(arcmsr_devclass, unit);
323f1c579b1SScott Long 	#endif
324f1c579b1SScott Long 
325ad6d6297SScott Long 	if(acb==NULL) {
326f1c579b1SScott Long 		return ENXIO;
327f1c579b1SScott Long 	}
328ad6d6297SScott Long 	return(arcmsr_iop_ioctlcmd(acb, ioctl_cmd, arg));
329f1c579b1SScott Long }
330f1c579b1SScott Long /*
33144f05562SScott Long **********************************************************************
33244f05562SScott Long **********************************************************************
33344f05562SScott Long */
33444f05562SScott Long static u_int32_t arcmsr_disable_allintr( struct AdapterControlBlock *acb)
33544f05562SScott Long {
33644f05562SScott Long 	u_int32_t intmask_org=0;
33744f05562SScott Long 
33844f05562SScott Long 	switch (acb->adapter_type) {
33944f05562SScott Long 	case ACB_ADAPTER_TYPE_A: {
34044f05562SScott Long 			/* disable all outbound interrupt */
341*d74001adSXin LI 			intmask_org=CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intmask); /* disable outbound message0 int */
342*d74001adSXin LI 			CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intmask, intmask_org|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE);
34344f05562SScott Long 		}
34444f05562SScott Long 		break;
34544f05562SScott Long 	case ACB_ADAPTER_TYPE_B: {
34644f05562SScott Long 			/* disable all outbound interrupt */
34744f05562SScott Long 			intmask_org=CHIP_REG_READ32(HBB_DOORBELL,
34844f05562SScott Long 			0, iop2drv_doorbell_mask) & (~ARCMSR_IOP2DRV_MESSAGE_CMD_DONE); /* disable outbound message0 int */
349*d74001adSXin LI 			CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell_mask, 0); /* disable all interrupt */
350*d74001adSXin LI 		}
351*d74001adSXin LI 		break;
352*d74001adSXin LI 	case ACB_ADAPTER_TYPE_C: {
353*d74001adSXin LI 			/* disable all outbound interrupt */
354*d74001adSXin LI 			intmask_org=CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_mask)	; /* disable outbound message0 int */
355*d74001adSXin LI 			CHIP_REG_WRITE32(HBC_MessageUnit, 0, host_int_mask, intmask_org|ARCMSR_HBCMU_ALL_INTMASKENABLE);
35644f05562SScott Long 		}
35744f05562SScott Long 		break;
35844f05562SScott Long 	}
35944f05562SScott Long 	return(intmask_org);
36044f05562SScott Long }
36144f05562SScott Long /*
36244f05562SScott Long **********************************************************************
36344f05562SScott Long **********************************************************************
36444f05562SScott Long */
36544f05562SScott Long static void arcmsr_enable_allintr( struct AdapterControlBlock *acb, u_int32_t intmask_org)
36644f05562SScott Long {
36744f05562SScott Long 	u_int32_t mask;
36844f05562SScott Long 
36944f05562SScott Long 	switch (acb->adapter_type) {
37044f05562SScott Long 	case ACB_ADAPTER_TYPE_A: {
37144f05562SScott Long 			/* enable outbound Post Queue, outbound doorbell Interrupt */
372*d74001adSXin LI 			mask=~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE|ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE|ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE);
37344f05562SScott Long 			CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intmask, intmask_org & mask);
37444f05562SScott Long 			acb->outbound_int_enable = ~(intmask_org & mask) & 0x000000ff;
37544f05562SScott Long 		}
37644f05562SScott Long 		break;
37744f05562SScott Long 	case ACB_ADAPTER_TYPE_B: {
378*d74001adSXin LI 			/* enable ARCMSR_IOP2DRV_MESSAGE_CMD_DONE */
379*d74001adSXin LI 			mask=(ARCMSR_IOP2DRV_DATA_WRITE_OK|ARCMSR_IOP2DRV_DATA_READ_OK|ARCMSR_IOP2DRV_CDB_DONE|ARCMSR_IOP2DRV_MESSAGE_CMD_DONE);
380*d74001adSXin LI 			CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell_mask, intmask_org | mask); /*1=interrupt enable, 0=interrupt disable*/
38144f05562SScott Long 			acb->outbound_int_enable = (intmask_org | mask) & 0x0000000f;
38244f05562SScott Long 		}
38344f05562SScott Long 		break;
384*d74001adSXin LI 	case ACB_ADAPTER_TYPE_C: {
385*d74001adSXin LI 			/* enable outbound Post Queue, outbound doorbell Interrupt */
386*d74001adSXin LI 			mask=~(ARCMSR_HBCMU_UTILITY_A_ISR_MASK | ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR_MASK | ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR_MASK);
387*d74001adSXin LI 			CHIP_REG_WRITE32(HBC_MessageUnit, 0, host_int_mask, intmask_org & mask);
388*d74001adSXin LI 			acb->outbound_int_enable= ~(intmask_org & mask) & 0x0000000f;
389*d74001adSXin LI 		}
390*d74001adSXin LI 		break;
39144f05562SScott Long 	}
39244f05562SScott Long 	return;
39344f05562SScott Long }
39444f05562SScott Long /*
39544f05562SScott Long **********************************************************************
39644f05562SScott Long **********************************************************************
39744f05562SScott Long */
39844f05562SScott Long static u_int8_t arcmsr_hba_wait_msgint_ready(struct AdapterControlBlock *acb)
39944f05562SScott Long {
40044f05562SScott Long 	u_int32_t Index;
40144f05562SScott Long 	u_int8_t Retries=0x00;
40244f05562SScott Long 
40344f05562SScott Long 	do {
40444f05562SScott Long 		for(Index=0; Index < 100; Index++) {
405*d74001adSXin LI 			if(CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) {
406*d74001adSXin LI 				CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, ARCMSR_MU_OUTBOUND_MESSAGE0_INT);/*clear interrupt*/
40744f05562SScott Long 				return TRUE;
40844f05562SScott Long 			}
40944f05562SScott Long 			UDELAY(10000);
41044f05562SScott Long 		}/*max 1 seconds*/
41144f05562SScott Long 	}while(Retries++ < 20);/*max 20 sec*/
41244f05562SScott Long 	return FALSE;
41344f05562SScott Long }
41444f05562SScott Long /*
41544f05562SScott Long **********************************************************************
41644f05562SScott Long **********************************************************************
41744f05562SScott Long */
41844f05562SScott Long static u_int8_t arcmsr_hbb_wait_msgint_ready(struct AdapterControlBlock *acb)
41944f05562SScott Long {
42044f05562SScott Long 	u_int32_t Index;
42144f05562SScott Long 	u_int8_t Retries=0x00;
42244f05562SScott Long 
42344f05562SScott Long 	do {
42444f05562SScott Long 		for(Index=0; Index < 100; Index++) {
425*d74001adSXin LI 			if(CHIP_REG_READ32(HBB_DOORBELL, 0, iop2drv_doorbell) & ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) {
426*d74001adSXin LI 				CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell, ARCMSR_MESSAGE_INT_CLEAR_PATTERN);/*clear interrupt*/
427*d74001adSXin LI 				CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT);
428*d74001adSXin LI 				return TRUE;
429*d74001adSXin LI 			}
430*d74001adSXin LI 			UDELAY(10000);
431*d74001adSXin LI 		}/*max 1 seconds*/
432*d74001adSXin LI 	}while(Retries++ < 20);/*max 20 sec*/
433*d74001adSXin LI 	return FALSE;
434*d74001adSXin LI }
435*d74001adSXin LI /*
436*d74001adSXin LI **********************************************************************
437*d74001adSXin LI **********************************************************************
438*d74001adSXin LI */
439*d74001adSXin LI static u_int8_t arcmsr_hbc_wait_msgint_ready(struct AdapterControlBlock *acb)
440*d74001adSXin LI {
441*d74001adSXin LI 	u_int32_t Index;
442*d74001adSXin LI 	u_int8_t Retries=0x00;
443*d74001adSXin LI 
444*d74001adSXin LI 	do {
445*d74001adSXin LI 		for(Index=0; Index < 100; Index++) {
446*d74001adSXin LI 			if(CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) {
447*d74001adSXin LI 				CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR);/*clear interrupt*/
44844f05562SScott Long 				return TRUE;
44944f05562SScott Long 			}
45044f05562SScott Long 			UDELAY(10000);
45144f05562SScott Long 		}/*max 1 seconds*/
45244f05562SScott Long 	}while(Retries++ < 20);/*max 20 sec*/
45344f05562SScott Long 	return FALSE;
45444f05562SScott Long }
45544f05562SScott Long /*
45644f05562SScott Long ************************************************************************
45744f05562SScott Long ************************************************************************
45844f05562SScott Long */
45944f05562SScott Long static void arcmsr_flush_hba_cache(struct AdapterControlBlock *acb)
46044f05562SScott Long {
46144f05562SScott Long 	int retry_count=30;/* enlarge wait flush adapter cache time: 10 minute */
46244f05562SScott Long 
463*d74001adSXin LI 	CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE);
46444f05562SScott Long 	do {
46544f05562SScott Long 		if(arcmsr_hba_wait_msgint_ready(acb)) {
46644f05562SScott Long 			break;
46744f05562SScott Long 		} else {
46844f05562SScott Long 			retry_count--;
46944f05562SScott Long 		}
47044f05562SScott Long 	}while(retry_count!=0);
47144f05562SScott Long 	return;
47244f05562SScott Long }
47344f05562SScott Long /*
47444f05562SScott Long ************************************************************************
47544f05562SScott Long ************************************************************************
47644f05562SScott Long */
47744f05562SScott Long static void arcmsr_flush_hbb_cache(struct AdapterControlBlock *acb)
47844f05562SScott Long {
47944f05562SScott Long 	int retry_count=30;/* enlarge wait flush adapter cache time: 10 minute */
48044f05562SScott Long 
48144f05562SScott Long 	CHIP_REG_WRITE32(HBB_DOORBELL,
48244f05562SScott Long 	0, drv2iop_doorbell, ARCMSR_MESSAGE_FLUSH_CACHE);
48344f05562SScott Long 	do {
48444f05562SScott Long 		if(arcmsr_hbb_wait_msgint_ready(acb)) {
48544f05562SScott Long 			break;
48644f05562SScott Long 		} else {
48744f05562SScott Long 			retry_count--;
48844f05562SScott Long 		}
48944f05562SScott Long 	}while(retry_count!=0);
49044f05562SScott Long 	return;
49144f05562SScott Long }
49244f05562SScott Long /*
49344f05562SScott Long ************************************************************************
49444f05562SScott Long ************************************************************************
49544f05562SScott Long */
496*d74001adSXin LI static void arcmsr_flush_hbc_cache(struct AdapterControlBlock *acb)
497*d74001adSXin LI {
498*d74001adSXin LI 	int retry_count=30;/* enlarge wait flush adapter cache time: 10 minute */
499*d74001adSXin LI 
500*d74001adSXin LI 	CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE);
501*d74001adSXin LI 	CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE);
502*d74001adSXin LI 	do {
503*d74001adSXin LI 		if(arcmsr_hbc_wait_msgint_ready(acb)) {
504*d74001adSXin LI 			break;
505*d74001adSXin LI 		} else {
506*d74001adSXin LI 			retry_count--;
507*d74001adSXin LI 		}
508*d74001adSXin LI 	}while(retry_count!=0);
509*d74001adSXin LI 	return;
510*d74001adSXin LI }
511*d74001adSXin LI /*
512*d74001adSXin LI ************************************************************************
513*d74001adSXin LI ************************************************************************
514*d74001adSXin LI */
51544f05562SScott Long static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb)
51644f05562SScott Long {
51744f05562SScott Long 	switch (acb->adapter_type) {
51844f05562SScott Long 	case ACB_ADAPTER_TYPE_A: {
51944f05562SScott Long 			arcmsr_flush_hba_cache(acb);
52044f05562SScott Long 		}
52144f05562SScott Long 		break;
52244f05562SScott Long 	case ACB_ADAPTER_TYPE_B: {
52344f05562SScott Long 			arcmsr_flush_hbb_cache(acb);
52444f05562SScott Long 		}
52544f05562SScott Long 		break;
526*d74001adSXin LI 	case ACB_ADAPTER_TYPE_C: {
527*d74001adSXin LI 			arcmsr_flush_hbc_cache(acb);
528*d74001adSXin LI 		}
529*d74001adSXin LI 		break;
53044f05562SScott Long 	}
53144f05562SScott Long 	return;
53244f05562SScott Long }
53344f05562SScott Long /*
534ad6d6297SScott Long *******************************************************************************
535ad6d6297SScott Long *******************************************************************************
536f1c579b1SScott Long */
537ad6d6297SScott Long static int arcmsr_suspend(device_t dev)
538f1c579b1SScott Long {
539ad6d6297SScott Long 	struct AdapterControlBlock	*acb = device_get_softc(dev);
540f1c579b1SScott Long 
541ad6d6297SScott Long 	/* flush controller */
542ad6d6297SScott Long 	arcmsr_iop_parking(acb);
543*d74001adSXin LI 	/* disable all outbound interrupt */
544*d74001adSXin LI 	arcmsr_disable_allintr(acb);
545ad6d6297SScott Long 	return(0);
546ad6d6297SScott Long }
547ad6d6297SScott Long /*
548ad6d6297SScott Long *******************************************************************************
549ad6d6297SScott Long *******************************************************************************
550ad6d6297SScott Long */
551ad6d6297SScott Long static int arcmsr_resume(device_t dev)
552ad6d6297SScott Long {
553ad6d6297SScott Long 	struct AdapterControlBlock	*acb = device_get_softc(dev);
554f1c579b1SScott Long 
555ad6d6297SScott Long 	arcmsr_iop_init(acb);
556ad6d6297SScott Long 	return(0);
557f1c579b1SScott Long }
558f1c579b1SScott Long /*
559f1c579b1SScott Long *********************************************************************************
560f1c579b1SScott Long *********************************************************************************
561f1c579b1SScott Long */
562ad6d6297SScott Long static void arcmsr_async(void *cb_arg, u_int32_t code, struct cam_path *path, void *arg)
563f1c579b1SScott Long {
564ad6d6297SScott Long 	struct AdapterControlBlock *acb;
565ad6d6297SScott Long 	u_int8_t target_id, target_lun;
566f1c579b1SScott Long 	struct cam_sim * sim;
567f1c579b1SScott Long 
568f1c579b1SScott Long 	sim=(struct cam_sim *) cb_arg;
569ad6d6297SScott Long 	acb =(struct AdapterControlBlock *) cam_sim_softc(sim);
570ad6d6297SScott Long 	switch (code) {
571f1c579b1SScott Long 	case AC_LOST_DEVICE:
572f1c579b1SScott Long 		target_id=xpt_path_target_id(path);
573f1c579b1SScott Long 		target_lun=xpt_path_lun_id(path);
574*d74001adSXin LI 		if((target_id > ARCMSR_MAX_TARGETID) || (target_lun > ARCMSR_MAX_TARGETLUN)) {
575f1c579b1SScott Long 			break;
576f1c579b1SScott Long 		}
577*d74001adSXin LI 		printf("%s:scsi id=%d lun=%d device lost \n", device_get_name(acb->pci_dev), target_id, target_lun);
578f1c579b1SScott Long 		break;
579f1c579b1SScott Long 	default:
580f1c579b1SScott Long 		break;
581f1c579b1SScott Long 	}
582f1c579b1SScott Long }
583f1c579b1SScott Long /*
584f1c579b1SScott Long **********************************************************************
585f1c579b1SScott Long **********************************************************************
586f1c579b1SScott Long */
587ad6d6297SScott Long static void arcmsr_srb_complete(struct CommandControlBlock *srb, int stand_flag)
588f1c579b1SScott Long {
589ad6d6297SScott Long 	struct AdapterControlBlock *acb=srb->acb;
590ad6d6297SScott Long 	union ccb * pccb=srb->pccb;
591f1c579b1SScott Long 
592ad6d6297SScott Long 	if((pccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
593f1c579b1SScott Long 		bus_dmasync_op_t op;
594f1c579b1SScott Long 
595ad6d6297SScott Long 		if((pccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
596f1c579b1SScott Long 			op = BUS_DMASYNC_POSTREAD;
597ad6d6297SScott Long 		} else {
598f1c579b1SScott Long 			op = BUS_DMASYNC_POSTWRITE;
599f1c579b1SScott Long 		}
600ad6d6297SScott Long 		bus_dmamap_sync(acb->dm_segs_dmat, srb->dm_segs_dmamap, op);
601ad6d6297SScott Long 		bus_dmamap_unload(acb->dm_segs_dmat, srb->dm_segs_dmamap);
602f1c579b1SScott Long 	}
603ad6d6297SScott Long 	if(stand_flag==1) {
604ad6d6297SScott Long 		atomic_subtract_int(&acb->srboutstandingcount, 1);
605dc3a205bSScott Long 		if((acb->acb_flags & ACB_F_CAM_DEV_QFRZN) && (
606dc3a205bSScott Long 		acb->srboutstandingcount < ARCMSR_RELEASE_SIMQ_LEVEL)) {
607dc3a205bSScott Long 			acb->acb_flags &= ~ACB_F_CAM_DEV_QFRZN;
608dc3a205bSScott Long 			pccb->ccb_h.status |= CAM_RELEASE_SIMQ;
609dc3a205bSScott Long 		}
610ad6d6297SScott Long 	}
611ad6d6297SScott Long 	srb->startdone=ARCMSR_SRB_DONE;
612ad6d6297SScott Long 	srb->srb_flags=0;
613ad6d6297SScott Long 	acb->srbworkingQ[acb->workingsrb_doneindex]=srb;
614ad6d6297SScott Long 	acb->workingsrb_doneindex++;
615ad6d6297SScott Long 	acb->workingsrb_doneindex %= ARCMSR_MAX_FREESRB_NUM;
616f1c579b1SScott Long 	xpt_done(pccb);
617f1c579b1SScott Long 	return;
618f1c579b1SScott Long }
619f1c579b1SScott Long /*
620f1c579b1SScott Long **********************************************************************
621f1c579b1SScott Long **********************************************************************
622f1c579b1SScott Long */
623ad6d6297SScott Long static void arcmsr_report_sense_info(struct CommandControlBlock *srb)
624f1c579b1SScott Long {
625ad6d6297SScott Long 	union ccb * pccb=srb->pccb;
626f1c579b1SScott Long 
627ad6d6297SScott Long 	pccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
628ad6d6297SScott Long 	pccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
629ad6d6297SScott Long 	if(&pccb->csio.sense_data) {
630ad6d6297SScott Long 		memset(&pccb->csio.sense_data, 0, sizeof(pccb->csio.sense_data));
631ad6d6297SScott Long 		memcpy(&pccb->csio.sense_data, srb->arcmsr_cdb.SenseData,
632ad6d6297SScott Long 		get_min(sizeof(struct SENSE_DATA), sizeof(pccb->csio.sense_data)));
633ad6d6297SScott Long 		((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70); /* Valid,ErrorCode */
634f1c579b1SScott Long 		pccb->ccb_h.status |= CAM_AUTOSNS_VALID;
635f1c579b1SScott Long 	}
636f1c579b1SScott Long 	return;
637f1c579b1SScott Long }
638f1c579b1SScott Long /*
639f1c579b1SScott Long *********************************************************************
64044f05562SScott Long *********************************************************************
64144f05562SScott Long */
64244f05562SScott Long static void arcmsr_abort_hba_allcmd(struct AdapterControlBlock *acb)
64344f05562SScott Long {
64444f05562SScott Long 	CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_ABORT_CMD);
64544f05562SScott Long 	if(!arcmsr_hba_wait_msgint_ready(acb)) {
646*d74001adSXin LI 		printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit);
64744f05562SScott Long 	}
64844f05562SScott Long 	return;
64944f05562SScott Long }
65044f05562SScott Long /*
65144f05562SScott Long *********************************************************************
65244f05562SScott Long *********************************************************************
65344f05562SScott Long */
65444f05562SScott Long static void arcmsr_abort_hbb_allcmd(struct AdapterControlBlock *acb)
65544f05562SScott Long {
65644f05562SScott Long 	CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_MESSAGE_ABORT_CMD);
65744f05562SScott Long 	if(!arcmsr_hbb_wait_msgint_ready(acb)) {
658*d74001adSXin LI 		printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit);
659*d74001adSXin LI 	}
660*d74001adSXin LI 	return;
661*d74001adSXin LI }
662*d74001adSXin LI /*
663*d74001adSXin LI *********************************************************************
664*d74001adSXin LI *********************************************************************
665*d74001adSXin LI */
666*d74001adSXin LI static void arcmsr_abort_hbc_allcmd(struct AdapterControlBlock *acb)
667*d74001adSXin LI {
668*d74001adSXin LI 	CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_ABORT_CMD);
669*d74001adSXin LI 	CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE);
670*d74001adSXin LI 	if(!arcmsr_hbc_wait_msgint_ready(acb)) {
671*d74001adSXin LI 		printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit);
67244f05562SScott Long 	}
67344f05562SScott Long 	return;
67444f05562SScott Long }
67544f05562SScott Long /*
67644f05562SScott Long *********************************************************************
677f1c579b1SScott Long *********************************************************************
678f1c579b1SScott Long */
679ad6d6297SScott Long static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb)
680f1c579b1SScott Long {
68144f05562SScott Long 	switch (acb->adapter_type) {
68244f05562SScott Long 	case ACB_ADAPTER_TYPE_A: {
68344f05562SScott Long 			arcmsr_abort_hba_allcmd(acb);
68444f05562SScott Long 		}
68544f05562SScott Long 		break;
68644f05562SScott Long 	case ACB_ADAPTER_TYPE_B: {
68744f05562SScott Long 			arcmsr_abort_hbb_allcmd(acb);
68844f05562SScott Long 		}
68944f05562SScott Long 		break;
690*d74001adSXin LI 	case ACB_ADAPTER_TYPE_C: {
691*d74001adSXin LI 			arcmsr_abort_hbc_allcmd(acb);
692*d74001adSXin LI 		}
693*d74001adSXin LI 		break;
69444f05562SScott Long 	}
69544f05562SScott Long 	return;
69644f05562SScott Long }
69744f05562SScott Long /*
69844f05562SScott Long **************************************************************************
69944f05562SScott Long **************************************************************************
70044f05562SScott Long */
701*d74001adSXin LI static void arcmsr_report_srb_state(struct AdapterControlBlock *acb, struct CommandControlBlock *srb, u_int16_t error)
70244f05562SScott Long {
70344f05562SScott Long 	int target, lun;
70444f05562SScott Long 
70544f05562SScott Long 	target=srb->pccb->ccb_h.target_id;
70644f05562SScott Long 	lun=srb->pccb->ccb_h.target_lun;
707*d74001adSXin LI 	if(error == FALSE) {
70844f05562SScott Long 		if(acb->devstate[target][lun]==ARECA_RAID_GONE) {
70944f05562SScott Long 			acb->devstate[target][lun]=ARECA_RAID_GOOD;
71044f05562SScott Long 		}
71144f05562SScott Long 		srb->pccb->ccb_h.status |= CAM_REQ_CMP;
71244f05562SScott Long 		arcmsr_srb_complete(srb, 1);
71344f05562SScott Long 	} else {
71444f05562SScott Long 		switch(srb->arcmsr_cdb.DeviceStatus) {
71544f05562SScott Long 		case ARCMSR_DEV_SELECT_TIMEOUT: {
71644f05562SScott Long 				if(acb->devstate[target][lun]==ARECA_RAID_GOOD) {
717*d74001adSXin LI 					printf( "arcmsr%d: Target=%x, Lun=%x, selection timeout, raid volume was lost\n", acb->pci_unit, target, lun);
718ad6d6297SScott Long 				}
71944f05562SScott Long 				acb->devstate[target][lun]=ARECA_RAID_GONE;
720*d74001adSXin LI 				srb->pccb->ccb_h.status |= CAM_DEV_NOT_THERE;
72144f05562SScott Long 				arcmsr_srb_complete(srb, 1);
72244f05562SScott Long 			}
72344f05562SScott Long 			break;
72444f05562SScott Long 		case ARCMSR_DEV_ABORTED:
72544f05562SScott Long 		case ARCMSR_DEV_INIT_FAIL: {
72644f05562SScott Long 				acb->devstate[target][lun]=ARECA_RAID_GONE;
72744f05562SScott Long 				srb->pccb->ccb_h.status |= CAM_DEV_NOT_THERE;
72844f05562SScott Long 				arcmsr_srb_complete(srb, 1);
72944f05562SScott Long 			}
73044f05562SScott Long 			break;
73144f05562SScott Long 		case SCSISTAT_CHECK_CONDITION: {
73244f05562SScott Long 				acb->devstate[target][lun]=ARECA_RAID_GOOD;
73344f05562SScott Long 				arcmsr_report_sense_info(srb);
73444f05562SScott Long 				arcmsr_srb_complete(srb, 1);
73544f05562SScott Long 			}
73644f05562SScott Long 			break;
73744f05562SScott Long 		default:
738*d74001adSXin LI 			printf("arcmsr%d: scsi id=%d lun=%d isr got command error done,but got unknow DeviceStatus=0x%x \n"
739*d74001adSXin LI 					, acb->pci_unit, target, lun ,srb->arcmsr_cdb.DeviceStatus);
74044f05562SScott Long 			acb->devstate[target][lun]=ARECA_RAID_GONE;
74144f05562SScott Long 			srb->pccb->ccb_h.status |= CAM_UNCOR_PARITY;
74244f05562SScott Long 			/*unknow error or crc error just for retry*/
74344f05562SScott Long 			arcmsr_srb_complete(srb, 1);
74444f05562SScott Long 			break;
74544f05562SScott Long 		}
74644f05562SScott Long 	}
74744f05562SScott Long 	return;
74844f05562SScott Long }
74944f05562SScott Long /*
75044f05562SScott Long **************************************************************************
75144f05562SScott Long **************************************************************************
75244f05562SScott Long */
753*d74001adSXin LI static void arcmsr_drain_donequeue(struct AdapterControlBlock *acb, u_int32_t flag_srb, u_int16_t error)
75444f05562SScott Long {
75544f05562SScott Long 	struct CommandControlBlock *srb;
75644f05562SScott Long 
75744f05562SScott Long 	/* check if command done with no error*/
758*d74001adSXin LI 	switch (acb->adapter_type) {
759*d74001adSXin LI 	case ACB_ADAPTER_TYPE_C:
760*d74001adSXin LI 		srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb & 0xFFFFFFF0));/*frame must be 32 bytes aligned*/
761*d74001adSXin LI 		break;
762*d74001adSXin LI 	case ACB_ADAPTER_TYPE_A:
763*d74001adSXin LI 	case ACB_ADAPTER_TYPE_B:
764*d74001adSXin LI 	default:
765*d74001adSXin LI 		srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/
766*d74001adSXin LI 		break;
767*d74001adSXin LI 	}
76844f05562SScott Long 	if((srb->acb!=acb) || (srb->startdone!=ARCMSR_SRB_START)) {
76944f05562SScott Long 		if(srb->startdone==ARCMSR_SRB_ABORTED) {
770*d74001adSXin LI 			printf("arcmsr%d: srb='%p' isr got aborted command \n", acb->pci_unit, srb);
77144f05562SScott Long 			srb->pccb->ccb_h.status |= CAM_REQ_ABORTED;
77244f05562SScott Long 			arcmsr_srb_complete(srb, 1);
77344f05562SScott Long 			return;
77444f05562SScott Long 		}
77544f05562SScott Long 		printf("arcmsr%d: isr get an illegal srb command done"
776*d74001adSXin LI 			"acb='%p' srb='%p' srbacb='%p' startdone=0x%xsrboutstandingcount=%d \n",
777*d74001adSXin LI 			acb->pci_unit, acb, srb, srb->acb,srb->startdone, acb->srboutstandingcount);
77844f05562SScott Long 		return;
77944f05562SScott Long 	}
780*d74001adSXin LI 	arcmsr_report_srb_state(acb, srb, error);
78144f05562SScott Long 	return;
78244f05562SScott Long }
78344f05562SScott Long /*
78444f05562SScott Long **********************************************************************
78544f05562SScott Long **********************************************************************
78644f05562SScott Long */
78744f05562SScott Long static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb)
78844f05562SScott Long {
78944f05562SScott Long 	int i=0;
79044f05562SScott Long 	u_int32_t flag_srb;
791*d74001adSXin LI 	u_int16_t error;
79244f05562SScott Long 
79344f05562SScott Long 	switch (acb->adapter_type) {
79444f05562SScott Long 	case ACB_ADAPTER_TYPE_A: {
79544f05562SScott Long 			u_int32_t outbound_intstatus;
79644f05562SScott Long 
79744f05562SScott Long 			/*clear and abort all outbound posted Q*/
798*d74001adSXin LI 			outbound_intstatus=CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & acb->outbound_int_enable;
799*d74001adSXin LI 			CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, outbound_intstatus);/*clear interrupt*/
800*d74001adSXin LI 			while(((flag_srb=CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_queueport)) != 0xFFFFFFFF) && (i++ < ARCMSR_MAX_OUTSTANDING_CMD)) {
801*d74001adSXin LI                 error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE;
802*d74001adSXin LI 				arcmsr_drain_donequeue(acb, flag_srb, error);
80344f05562SScott Long 			}
80444f05562SScott Long 		}
80544f05562SScott Long 		break;
80644f05562SScott Long 	case ACB_ADAPTER_TYPE_B: {
80744f05562SScott Long 			struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu;
80844f05562SScott Long 
80944f05562SScott Long 			/*clear all outbound posted Q*/
810*d74001adSXin LI 			CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell, ARCMSR_DOORBELL_INT_CLEAR_PATTERN); /* clear doorbell interrupt */
81144f05562SScott Long 			for(i=0; i < ARCMSR_MAX_HBB_POSTQUEUE; i++) {
81244f05562SScott Long 				if((flag_srb=phbbmu->done_qbuffer[i])!=0) {
81344f05562SScott Long 					phbbmu->done_qbuffer[i]=0;
814*d74001adSXin LI                 	error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE;
815*d74001adSXin LI 					arcmsr_drain_donequeue(acb, flag_srb, error);
81644f05562SScott Long 				}
81744f05562SScott Long 				phbbmu->post_qbuffer[i]=0;
81844f05562SScott Long 			}/*drain reply FIFO*/
81944f05562SScott Long 			phbbmu->doneq_index=0;
82044f05562SScott Long 			phbbmu->postq_index=0;
82144f05562SScott Long 		}
82244f05562SScott Long 		break;
823*d74001adSXin LI 	case ACB_ADAPTER_TYPE_C: {
824*d74001adSXin LI 
825*d74001adSXin LI 			while((CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) && (i++ < ARCMSR_MAX_OUTSTANDING_CMD)) {
826*d74001adSXin LI 				flag_srb=CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_queueport_low);
827*d74001adSXin LI                 error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1)?TRUE:FALSE;
828*d74001adSXin LI 				arcmsr_drain_donequeue(acb, flag_srb, error);
829*d74001adSXin LI 			}
830*d74001adSXin LI 		}
831*d74001adSXin LI 		break;
83244f05562SScott Long 	}
833f1c579b1SScott Long 	return;
834f1c579b1SScott Long }
835f1c579b1SScott Long /*
836f1c579b1SScott Long ****************************************************************************
837f1c579b1SScott Long ****************************************************************************
838f1c579b1SScott Long */
839ad6d6297SScott Long static void arcmsr_iop_reset(struct AdapterControlBlock *acb)
840f1c579b1SScott Long {
841ad6d6297SScott Long 	struct CommandControlBlock *srb;
84244f05562SScott Long 	u_int32_t intmask_org;
843ad6d6297SScott Long 	u_int32_t i=0;
844f1c579b1SScott Long 
84544f05562SScott Long 	if(acb->srboutstandingcount>0) {
84644f05562SScott Long 		/* disable all outbound interrupt */
84744f05562SScott Long 		intmask_org=arcmsr_disable_allintr(acb);
84844f05562SScott Long 		/*clear and abort all outbound posted Q*/
84944f05562SScott Long 		arcmsr_done4abort_postqueue(acb);
850f1c579b1SScott Long 		/* talk to iop 331 outstanding command aborted*/
851ad6d6297SScott Long 		arcmsr_abort_allcmd(acb);
852ad6d6297SScott Long 		for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++) {
853ad6d6297SScott Long 			srb=acb->psrb_pool[i];
854ad6d6297SScott Long 			if(srb->startdone==ARCMSR_SRB_START) {
855ad6d6297SScott Long 				srb->startdone=ARCMSR_SRB_ABORTED;
856ad6d6297SScott Long 				srb->pccb->ccb_h.status |= CAM_REQ_ABORTED;
857ad6d6297SScott Long 				arcmsr_srb_complete(srb, 1);
858f1c579b1SScott Long 			}
859f1c579b1SScott Long 		}
860f1c579b1SScott Long 		/* enable all outbound interrupt */
86144f05562SScott Long 		arcmsr_enable_allintr(acb, intmask_org);
862f1c579b1SScott Long 	}
863ad6d6297SScott Long 	atomic_set_int(&acb->srboutstandingcount, 0);
864ad6d6297SScott Long 	acb->workingsrb_doneindex=0;
865ad6d6297SScott Long 	acb->workingsrb_startindex=0;
866f1c579b1SScott Long 	return;
867f1c579b1SScott Long }
868f1c579b1SScott Long /*
869f1c579b1SScott Long **********************************************************************
870f1c579b1SScott Long **********************************************************************
871f1c579b1SScott Long */
87244f05562SScott Long static void arcmsr_build_srb(struct CommandControlBlock *srb,
87344f05562SScott Long 		bus_dma_segment_t *dm_segs, u_int32_t nseg)
874f1c579b1SScott Long {
875ad6d6297SScott Long 	struct ARCMSR_CDB * arcmsr_cdb= &srb->arcmsr_cdb;
876ad6d6297SScott Long 	u_int8_t * psge=(u_int8_t *)&arcmsr_cdb->u;
877ad6d6297SScott Long 	u_int32_t address_lo, address_hi;
878ad6d6297SScott Long 	union ccb * pccb=srb->pccb;
879f1c579b1SScott Long 	struct ccb_scsiio * pcsio= &pccb->csio;
880ad6d6297SScott Long 	u_int32_t arccdbsize=0x30;
881f1c579b1SScott Long 
882ad6d6297SScott Long 	memset(arcmsr_cdb, 0, sizeof(struct ARCMSR_CDB));
883ad6d6297SScott Long 	arcmsr_cdb->Bus=0;
884ad6d6297SScott Long 	arcmsr_cdb->TargetID=pccb->ccb_h.target_id;
885ad6d6297SScott Long 	arcmsr_cdb->LUN=pccb->ccb_h.target_lun;
886ad6d6297SScott Long 	arcmsr_cdb->Function=1;
887ad6d6297SScott Long 	arcmsr_cdb->CdbLength=(u_int8_t)pcsio->cdb_len;
88844f05562SScott Long 	arcmsr_cdb->Context=0;
889ad6d6297SScott Long 	bcopy(pcsio->cdb_io.cdb_bytes, arcmsr_cdb->Cdb, pcsio->cdb_len);
890ad6d6297SScott Long 	if(nseg != 0) {
891ad6d6297SScott Long 		struct AdapterControlBlock *acb=srb->acb;
892f1c579b1SScott Long 		bus_dmasync_op_t op;
893ad6d6297SScott Long 		u_int32_t length, i, cdb_sgcount=0;
894f1c579b1SScott Long 
895ad6d6297SScott Long 		if((pccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
896ad6d6297SScott Long 			op=BUS_DMASYNC_PREREAD;
897ad6d6297SScott Long 		} else {
898ad6d6297SScott Long 			op=BUS_DMASYNC_PREWRITE;
899ad6d6297SScott Long 			arcmsr_cdb->Flags|=ARCMSR_CDB_FLAG_WRITE;
900ad6d6297SScott Long 			srb->srb_flags|=SRB_FLAG_WRITE;
901ad6d6297SScott Long 		}
902ad6d6297SScott Long 		bus_dmamap_sync(acb->dm_segs_dmat, srb->dm_segs_dmamap, op);
903ad6d6297SScott Long 		for(i=0;i<nseg;i++) {
904f1c579b1SScott Long 			/* Get the physical address of the current data pointer */
905ad6d6297SScott Long 			length=arcmsr_htole32(dm_segs[i].ds_len);
906ad6d6297SScott Long 			address_lo=arcmsr_htole32(dma_addr_lo32(dm_segs[i].ds_addr));
907ad6d6297SScott Long 			address_hi=arcmsr_htole32(dma_addr_hi32(dm_segs[i].ds_addr));
908ad6d6297SScott Long 			if(address_hi==0) {
909ad6d6297SScott Long 				struct SG32ENTRY * pdma_sg=(struct SG32ENTRY *)psge;
910f1c579b1SScott Long 				pdma_sg->address=address_lo;
911f1c579b1SScott Long 				pdma_sg->length=length;
912ad6d6297SScott Long 				psge += sizeof(struct SG32ENTRY);
913ad6d6297SScott Long 				arccdbsize += sizeof(struct SG32ENTRY);
914ad6d6297SScott Long 			} else {
915ad6d6297SScott Long 				u_int32_t sg64s_size=0, tmplength=length;
916f1c579b1SScott Long 
917ad6d6297SScott Long 				while(1) {
918ad6d6297SScott Long 					u_int64_t span4G, length0;
919ad6d6297SScott Long 					struct SG64ENTRY * pdma_sg=(struct SG64ENTRY *)psge;
920f1c579b1SScott Long 
921ad6d6297SScott Long 					span4G=(u_int64_t)address_lo + tmplength;
922f1c579b1SScott Long 					pdma_sg->addresshigh=address_hi;
923f1c579b1SScott Long 					pdma_sg->address=address_lo;
924ad6d6297SScott Long 					if(span4G > 0x100000000) {
925f1c579b1SScott Long 						/*see if cross 4G boundary*/
926f1c579b1SScott Long 						length0=0x100000000-address_lo;
927ad6d6297SScott Long 						pdma_sg->length=(u_int32_t)length0|IS_SG64_ADDR;
928f1c579b1SScott Long 						address_hi=address_hi+1;
929f1c579b1SScott Long 						address_lo=0;
930ad6d6297SScott Long 						tmplength=tmplength-(u_int32_t)length0;
931ad6d6297SScott Long 						sg64s_size += sizeof(struct SG64ENTRY);
932ad6d6297SScott Long 						psge += sizeof(struct SG64ENTRY);
933f1c579b1SScott Long 						cdb_sgcount++;
934ad6d6297SScott Long 					} else {
935f1c579b1SScott Long 						pdma_sg->length=tmplength|IS_SG64_ADDR;
936ad6d6297SScott Long 						sg64s_size += sizeof(struct SG64ENTRY);
937ad6d6297SScott Long 						psge += sizeof(struct SG64ENTRY);
938f1c579b1SScott Long 						break;
939f1c579b1SScott Long 					}
940f1c579b1SScott Long 				}
941f1c579b1SScott Long 				arccdbsize += sg64s_size;
942f1c579b1SScott Long 			}
943f1c579b1SScott Long 			cdb_sgcount++;
944f1c579b1SScott Long 		}
945ad6d6297SScott Long 		arcmsr_cdb->sgcount=(u_int8_t)cdb_sgcount;
946ad6d6297SScott Long 		arcmsr_cdb->DataLength=pcsio->dxfer_len;
947ad6d6297SScott Long 		if( arccdbsize > 256) {
948ad6d6297SScott Long 			arcmsr_cdb->Flags|=ARCMSR_CDB_FLAG_SGL_BSIZE;
949f1c579b1SScott Long 		}
950*d74001adSXin LI 	} else {
951*d74001adSXin LI 		arcmsr_cdb->DataLength = 0;
952f1c579b1SScott Long 	}
953*d74001adSXin LI     srb->arc_cdb_size=arccdbsize;
954f1c579b1SScott Long 	return;
955f1c579b1SScott Long }
956f1c579b1SScott Long /*
957f1c579b1SScott Long **************************************************************************
958f1c579b1SScott Long **************************************************************************
959f1c579b1SScott Long */
960ad6d6297SScott Long static void arcmsr_post_srb(struct AdapterControlBlock *acb, struct CommandControlBlock *srb)
961f1c579b1SScott Long {
962ad6d6297SScott Long 	u_int32_t cdb_shifted_phyaddr=(u_int32_t) srb->cdb_shifted_phyaddr;
963ad6d6297SScott Long 	struct ARCMSR_CDB * arcmsr_cdb=(struct ARCMSR_CDB *)&srb->arcmsr_cdb;
964f1c579b1SScott Long 
965*d74001adSXin LI 	bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, (srb->srb_flags & SRB_FLAG_WRITE) ? BUS_DMASYNC_POSTWRITE:BUS_DMASYNC_POSTREAD);
966ad6d6297SScott Long 	atomic_add_int(&acb->srboutstandingcount, 1);
967ad6d6297SScott Long 	srb->startdone=ARCMSR_SRB_START;
968*d74001adSXin LI 
96944f05562SScott Long 	switch (acb->adapter_type) {
97044f05562SScott Long 	case ACB_ADAPTER_TYPE_A: {
971ad6d6297SScott Long 			if(arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) {
972*d74001adSXin LI 				CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_queueport, cdb_shifted_phyaddr|ARCMSR_SRBPOST_FLAG_SGL_BSIZE);
973ad6d6297SScott Long 			} else {
974*d74001adSXin LI 				CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_queueport, cdb_shifted_phyaddr);
97544f05562SScott Long 			}
97644f05562SScott Long 		}
97744f05562SScott Long 		break;
97844f05562SScott Long 	case ACB_ADAPTER_TYPE_B: {
97944f05562SScott Long 			struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu;
98044f05562SScott Long 			int ending_index, index;
98144f05562SScott Long 
98244f05562SScott Long 			index=phbbmu->postq_index;
98344f05562SScott Long 			ending_index=((index+1)%ARCMSR_MAX_HBB_POSTQUEUE);
98444f05562SScott Long 			phbbmu->post_qbuffer[ending_index]=0;
98544f05562SScott Long 			if(arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) {
986*d74001adSXin LI 				phbbmu->post_qbuffer[index]= cdb_shifted_phyaddr|ARCMSR_SRBPOST_FLAG_SGL_BSIZE;
98744f05562SScott Long 			} else {
988*d74001adSXin LI 				phbbmu->post_qbuffer[index]= cdb_shifted_phyaddr;
98944f05562SScott Long 			}
99044f05562SScott Long 			index++;
99144f05562SScott Long 			index %= ARCMSR_MAX_HBB_POSTQUEUE;     /*if last index number set it to 0 */
99244f05562SScott Long 			phbbmu->postq_index=index;
993*d74001adSXin LI 			CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_CDB_POSTED);
994*d74001adSXin LI 		}
995*d74001adSXin LI 		break;
996*d74001adSXin LI     case ACB_ADAPTER_TYPE_C:
997*d74001adSXin LI         {
998*d74001adSXin LI             u_int32_t ccb_post_stamp, arc_cdb_size, cdb_phyaddr_hi32;
999*d74001adSXin LI 
1000*d74001adSXin LI             arc_cdb_size=(srb->arc_cdb_size>0x300)?0x300:srb->arc_cdb_size;
1001*d74001adSXin LI             ccb_post_stamp=(cdb_shifted_phyaddr | ((arc_cdb_size-1) >> 6) | 1);
1002*d74001adSXin LI 			cdb_phyaddr_hi32 = acb->srb_phyaddr.B.phyadd_high;
1003*d74001adSXin LI             if(cdb_phyaddr_hi32)
1004*d74001adSXin LI             {
1005*d74001adSXin LI 			    CHIP_REG_WRITE32(HBC_MessageUnit,0,inbound_queueport_high, cdb_phyaddr_hi32);
1006*d74001adSXin LI 			    CHIP_REG_WRITE32(HBC_MessageUnit,0,inbound_queueport_low, ccb_post_stamp);
1007*d74001adSXin LI             }
1008*d74001adSXin LI             else
1009*d74001adSXin LI             {
1010*d74001adSXin LI 			    CHIP_REG_WRITE32(HBC_MessageUnit,0,inbound_queueport_low, ccb_post_stamp);
1011*d74001adSXin LI             }
101244f05562SScott Long 		}
101344f05562SScott Long 		break;
1014f1c579b1SScott Long 	}
1015f1c579b1SScott Long 	return;
1016f1c579b1SScott Long }
1017f1c579b1SScott Long /*
101844f05562SScott Long ************************************************************************
101944f05562SScott Long ************************************************************************
102044f05562SScott Long */
102144f05562SScott Long static struct QBUFFER * arcmsr_get_iop_rqbuffer( struct AdapterControlBlock *acb)
102244f05562SScott Long {
102344f05562SScott Long 	struct QBUFFER *qbuffer=NULL;
102444f05562SScott Long 
102544f05562SScott Long 	switch (acb->adapter_type) {
102644f05562SScott Long 	case ACB_ADAPTER_TYPE_A: {
102744f05562SScott Long 			struct HBA_MessageUnit *phbamu=(struct HBA_MessageUnit *)acb->pmu;
102844f05562SScott Long 
102944f05562SScott Long 			qbuffer=(struct QBUFFER *)&phbamu->message_rbuffer;
103044f05562SScott Long 		}
103144f05562SScott Long 		break;
103244f05562SScott Long 	case ACB_ADAPTER_TYPE_B: {
103344f05562SScott Long 			struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu;
103444f05562SScott Long 
103544f05562SScott Long 			qbuffer=(struct QBUFFER *)&phbbmu->hbb_rwbuffer->message_rbuffer;
103644f05562SScott Long 		}
103744f05562SScott Long 		break;
1038*d74001adSXin LI 	case ACB_ADAPTER_TYPE_C: {
1039*d74001adSXin LI 			struct HBC_MessageUnit *phbcmu=(struct HBC_MessageUnit *)acb->pmu;
1040*d74001adSXin LI 
1041*d74001adSXin LI 			qbuffer=(struct QBUFFER *)&phbcmu->message_rbuffer;
1042*d74001adSXin LI 		}
1043*d74001adSXin LI 		break;
104444f05562SScott Long 	}
104544f05562SScott Long 	return(qbuffer);
104644f05562SScott Long }
104744f05562SScott Long /*
104844f05562SScott Long ************************************************************************
104944f05562SScott Long ************************************************************************
105044f05562SScott Long */
105144f05562SScott Long static struct QBUFFER * arcmsr_get_iop_wqbuffer( struct AdapterControlBlock *acb)
105244f05562SScott Long {
105344f05562SScott Long 	struct QBUFFER *qbuffer=NULL;
105444f05562SScott Long 
105544f05562SScott Long 	switch (acb->adapter_type) {
105644f05562SScott Long 	case ACB_ADAPTER_TYPE_A: {
105744f05562SScott Long 			struct HBA_MessageUnit *phbamu=(struct HBA_MessageUnit *)acb->pmu;
105844f05562SScott Long 
105944f05562SScott Long 			qbuffer=(struct QBUFFER *)&phbamu->message_wbuffer;
106044f05562SScott Long 		}
106144f05562SScott Long 		break;
106244f05562SScott Long 	case ACB_ADAPTER_TYPE_B: {
106344f05562SScott Long 			struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu;
106444f05562SScott Long 
106544f05562SScott Long 			qbuffer=(struct QBUFFER *)&phbbmu->hbb_rwbuffer->message_wbuffer;
106644f05562SScott Long 		}
106744f05562SScott Long 		break;
1068*d74001adSXin LI 	case ACB_ADAPTER_TYPE_C: {
1069*d74001adSXin LI 			struct HBC_MessageUnit *phbcmu=(struct HBC_MessageUnit *)acb->pmu;
1070*d74001adSXin LI 
1071*d74001adSXin LI 			qbuffer=(struct QBUFFER *)&phbcmu->message_wbuffer;
1072*d74001adSXin LI 		}
1073*d74001adSXin LI 		break;
107444f05562SScott Long 	}
107544f05562SScott Long 	return(qbuffer);
107644f05562SScott Long }
107744f05562SScott Long /*
107844f05562SScott Long **************************************************************************
107944f05562SScott Long **************************************************************************
108044f05562SScott Long */
108144f05562SScott Long static void arcmsr_iop_message_read(struct AdapterControlBlock *acb)
108244f05562SScott Long {
108344f05562SScott Long 	switch (acb->adapter_type) {
108444f05562SScott Long 	case ACB_ADAPTER_TYPE_A: {
108544f05562SScott Long 			/* let IOP know data has been read */
1086*d74001adSXin LI 			CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK);
108744f05562SScott Long 		}
108844f05562SScott Long 		break;
108944f05562SScott Long 	case ACB_ADAPTER_TYPE_B: {
109044f05562SScott Long 			/* let IOP know data has been read */
1091*d74001adSXin LI 			CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_READ_OK);
109244f05562SScott Long 		}
109344f05562SScott Long 		break;
1094*d74001adSXin LI 	case ACB_ADAPTER_TYPE_C: {
1095*d74001adSXin LI 			/* let IOP know data has been read */
1096*d74001adSXin LI 			CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK);
1097*d74001adSXin LI 		}
109844f05562SScott Long 	}
109944f05562SScott Long 	return;
110044f05562SScott Long }
110144f05562SScott Long /*
110244f05562SScott Long **************************************************************************
110344f05562SScott Long **************************************************************************
110444f05562SScott Long */
110544f05562SScott Long static void arcmsr_iop_message_wrote(struct AdapterControlBlock *acb)
110644f05562SScott Long {
110744f05562SScott Long 	switch (acb->adapter_type) {
110844f05562SScott Long 	case ACB_ADAPTER_TYPE_A: {
110944f05562SScott Long 			/*
111044f05562SScott Long 			** push inbound doorbell tell iop, driver data write ok
111144f05562SScott Long 			** and wait reply on next hwinterrupt for next Qbuffer post
111244f05562SScott Long 			*/
1113*d74001adSXin LI 			CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK);
111444f05562SScott Long 		}
111544f05562SScott Long 		break;
111644f05562SScott Long 	case ACB_ADAPTER_TYPE_B: {
111744f05562SScott Long 			/*
111844f05562SScott Long 			** push inbound doorbell tell iop, driver data write ok
111944f05562SScott Long 			** and wait reply on next hwinterrupt for next Qbuffer post
112044f05562SScott Long 			*/
1121*d74001adSXin LI 			CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_WRITE_OK);
1122*d74001adSXin LI 		}
1123*d74001adSXin LI 		break;
1124*d74001adSXin LI 	case ACB_ADAPTER_TYPE_C: {
1125*d74001adSXin LI 			/*
1126*d74001adSXin LI 			** push inbound doorbell tell iop, driver data write ok
1127*d74001adSXin LI 			** and wait reply on next hwinterrupt for next Qbuffer post
1128*d74001adSXin LI 			*/
1129*d74001adSXin LI 			CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_DATA_WRITE_OK);
113044f05562SScott Long 		}
113144f05562SScott Long 		break;
113244f05562SScott Long 	}
113344f05562SScott Long }
113444f05562SScott Long /*
1135f1c579b1SScott Long **********************************************************************
1136f1c579b1SScott Long **********************************************************************
1137f1c579b1SScott Long */
113844f05562SScott Long static void arcmsr_post_ioctldata2iop(struct AdapterControlBlock *acb)
1139f1c579b1SScott Long {
1140ad6d6297SScott Long 	u_int8_t *pQbuffer;
114144f05562SScott Long 	struct QBUFFER *pwbuffer;
114244f05562SScott Long 	u_int8_t * iop_data;
114344f05562SScott Long 	int32_t allxfer_len=0;
1144f1c579b1SScott Long 
114544f05562SScott Long 	pwbuffer=arcmsr_get_iop_wqbuffer(acb);
114644f05562SScott Long 	iop_data=(u_int8_t *)pwbuffer->data;
114744f05562SScott Long 	if(acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_READ) {
114844f05562SScott Long 		acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READ);
114944f05562SScott Long 		while((acb->wqbuf_firstindex!=acb->wqbuf_lastindex)
115044f05562SScott Long 			&& (allxfer_len<124)) {
1151ad6d6297SScott Long 			pQbuffer=&acb->wqbuffer[acb->wqbuf_firstindex];
1152f1c579b1SScott Long 			memcpy(iop_data, pQbuffer, 1);
1153ad6d6297SScott Long 			acb->wqbuf_firstindex++;
115444f05562SScott Long 			acb->wqbuf_firstindex %=ARCMSR_MAX_QBUFFER; /*if last index number set it to 0 */
1155f1c579b1SScott Long 			iop_data++;
1156f1c579b1SScott Long 			allxfer_len++;
1157f1c579b1SScott Long 		}
1158f1c579b1SScott Long 		pwbuffer->data_len=allxfer_len;
1159f1c579b1SScott Long 		/*
1160f1c579b1SScott Long 		** push inbound doorbell and wait reply at hwinterrupt routine for next Qbuffer post
1161f1c579b1SScott Long 		*/
116244f05562SScott Long 		arcmsr_iop_message_wrote(acb);
1163ad6d6297SScott Long 	}
1164f1c579b1SScott Long 	return;
1165f1c579b1SScott Long }
1166f1c579b1SScott Long /*
1167f1c579b1SScott Long ************************************************************************
1168f1c579b1SScott Long ************************************************************************
1169f1c579b1SScott Long */
117044f05562SScott Long static void arcmsr_stop_hba_bgrb(struct AdapterControlBlock *acb)
1171f1c579b1SScott Long {
1172ad6d6297SScott Long 	acb->acb_flags &=~ACB_F_MSG_START_BGRB;
117344f05562SScott Long 	CHIP_REG_WRITE32(HBA_MessageUnit,
117444f05562SScott Long 	0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB);
117544f05562SScott Long 	if(!arcmsr_hba_wait_msgint_ready(acb)) {
1176*d74001adSXin LI 		printf("arcmsr%d: wait 'stop adapter background rebulid' timeout \n"
1177ad6d6297SScott Long 			, acb->pci_unit);
1178ad6d6297SScott Long 	}
1179f1c579b1SScott Long 	return;
1180f1c579b1SScott Long }
1181f1c579b1SScott Long /*
1182f1c579b1SScott Long ************************************************************************
1183f1c579b1SScott Long ************************************************************************
1184f1c579b1SScott Long */
118544f05562SScott Long static void arcmsr_stop_hbb_bgrb(struct AdapterControlBlock *acb)
118644f05562SScott Long {
118744f05562SScott Long 	acb->acb_flags &= ~ACB_F_MSG_START_BGRB;
118844f05562SScott Long 	CHIP_REG_WRITE32(HBB_DOORBELL,
118944f05562SScott Long 	0, drv2iop_doorbell, ARCMSR_MESSAGE_STOP_BGRB);
119044f05562SScott Long 	if(!arcmsr_hbb_wait_msgint_ready(acb)) {
1191*d74001adSXin LI 		printf( "arcmsr%d: wait 'stop adapter background rebulid' timeout \n"
119244f05562SScott Long 			, acb->pci_unit);
119344f05562SScott Long 	}
119444f05562SScott Long 	return;
119544f05562SScott Long }
119644f05562SScott Long /*
119744f05562SScott Long ************************************************************************
119844f05562SScott Long ************************************************************************
119944f05562SScott Long */
1200*d74001adSXin LI static void arcmsr_stop_hbc_bgrb(struct AdapterControlBlock *acb)
1201*d74001adSXin LI {
1202*d74001adSXin LI 	acb->acb_flags &=~ACB_F_MSG_START_BGRB;
1203*d74001adSXin LI 	CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB);
1204*d74001adSXin LI 	CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell,ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE);
1205*d74001adSXin LI 	if(!arcmsr_hbc_wait_msgint_ready(acb)) {
1206*d74001adSXin LI 		printf("arcmsr%d: wait 'stop adapter background rebulid' timeout \n", acb->pci_unit);
1207*d74001adSXin LI 	}
1208*d74001adSXin LI 	return;
1209*d74001adSXin LI }
1210*d74001adSXin LI /*
1211*d74001adSXin LI ************************************************************************
1212*d74001adSXin LI ************************************************************************
1213*d74001adSXin LI */
121444f05562SScott Long static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb)
121544f05562SScott Long {
121644f05562SScott Long 	switch (acb->adapter_type) {
121744f05562SScott Long 	case ACB_ADAPTER_TYPE_A: {
121844f05562SScott Long 			arcmsr_stop_hba_bgrb(acb);
121944f05562SScott Long 		}
122044f05562SScott Long 		break;
122144f05562SScott Long 	case ACB_ADAPTER_TYPE_B: {
122244f05562SScott Long 			arcmsr_stop_hbb_bgrb(acb);
122344f05562SScott Long 		}
122444f05562SScott Long 		break;
1225*d74001adSXin LI 	case ACB_ADAPTER_TYPE_C: {
1226*d74001adSXin LI 			arcmsr_stop_hbc_bgrb(acb);
1227*d74001adSXin LI 		}
1228*d74001adSXin LI 		break;
122944f05562SScott Long 	}
123044f05562SScott Long 	return;
123144f05562SScott Long }
123244f05562SScott Long /*
123344f05562SScott Long ************************************************************************
123444f05562SScott Long ************************************************************************
123544f05562SScott Long */
1236ad6d6297SScott Long static void arcmsr_poll(struct cam_sim * psim)
1237f1c579b1SScott Long {
1238579ec1a5SScott Long 	struct AdapterControlBlock *acb;
1239579ec1a5SScott Long 
1240579ec1a5SScott Long 	acb = (struct AdapterControlBlock *)cam_sim_softc(psim);
1241579ec1a5SScott Long #if __FreeBSD_version < 700025
1242579ec1a5SScott Long 	ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
1243579ec1a5SScott Long #endif
1244579ec1a5SScott Long 	arcmsr_interrupt(acb);
1245579ec1a5SScott Long #if __FreeBSD_version < 700025
1246579ec1a5SScott Long 	ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
1247579ec1a5SScott Long #endif
1248f1c579b1SScott Long 	return;
1249f1c579b1SScott Long }
1250f1c579b1SScott Long /*
125144f05562SScott Long **************************************************************************
125244f05562SScott Long **************************************************************************
12535878cbecSScott Long */
125444f05562SScott Long static void arcmsr_iop2drv_data_wrote_handle(struct AdapterControlBlock *acb)
1255f1c579b1SScott Long {
125644f05562SScott Long 	struct QBUFFER *prbuffer;
1257ad6d6297SScott Long 	u_int8_t *pQbuffer;
125844f05562SScott Long 	u_int8_t *iop_data;
125944f05562SScott Long 	int my_empty_len, iop_len, rqbuf_firstindex, rqbuf_lastindex;
1260ad6d6297SScott Long 
1261f1c579b1SScott Long 	/*check this iop data if overflow my rqbuffer*/
1262ad6d6297SScott Long 	rqbuf_lastindex=acb->rqbuf_lastindex;
1263ad6d6297SScott Long 	rqbuf_firstindex=acb->rqbuf_firstindex;
126444f05562SScott Long 	prbuffer=arcmsr_get_iop_rqbuffer(acb);
126544f05562SScott Long 	iop_data=(u_int8_t *)prbuffer->data;
1266f1c579b1SScott Long 	iop_len=prbuffer->data_len;
1267f1c579b1SScott Long 	my_empty_len=(rqbuf_firstindex-rqbuf_lastindex-1)&(ARCMSR_MAX_QBUFFER-1);
1268ad6d6297SScott Long 	if(my_empty_len>=iop_len) {
1269ad6d6297SScott Long 		while(iop_len > 0) {
127044f05562SScott Long 			pQbuffer=&acb->rqbuffer[rqbuf_lastindex];
1271f1c579b1SScott Long 			memcpy(pQbuffer, iop_data, 1);
127244f05562SScott Long 			rqbuf_lastindex++;
127344f05562SScott Long 			rqbuf_lastindex %= ARCMSR_MAX_QBUFFER;/*if last index number set it to 0 */
1274f1c579b1SScott Long 			iop_data++;
1275f1c579b1SScott Long 			iop_len--;
1276f1c579b1SScott Long 		}
127744f05562SScott Long 		acb->rqbuf_lastindex=rqbuf_lastindex;
127844f05562SScott Long 		arcmsr_iop_message_read(acb);
127944f05562SScott Long 		/*signature, let IOP know data has been read */
1280ad6d6297SScott Long 	} else {
1281ad6d6297SScott Long 		acb->acb_flags|=ACB_F_IOPDATA_OVERFLOW;
1282f1c579b1SScott Long 	}
128344f05562SScott Long 	return;
1284f1c579b1SScott Long }
1285f1c579b1SScott Long /*
128644f05562SScott Long **************************************************************************
128744f05562SScott Long **************************************************************************
128844f05562SScott Long */
128944f05562SScott Long static void arcmsr_iop2drv_data_read_handle(struct AdapterControlBlock *acb)
129044f05562SScott Long {
129144f05562SScott Long 	acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_READ;
129244f05562SScott Long 	/*
129344f05562SScott Long 	*****************************************************************
129444f05562SScott Long 	**   check if there are any mail packages from user space program
129544f05562SScott Long 	**   in my post bag, now is the time to send them into Areca's firmware
129644f05562SScott Long 	*****************************************************************
1297f1c579b1SScott Long 	*/
1298ad6d6297SScott Long 	if(acb->wqbuf_firstindex!=acb->wqbuf_lastindex) {
1299ad6d6297SScott Long 		u_int8_t *pQbuffer;
130044f05562SScott Long 		struct QBUFFER *pwbuffer;
130144f05562SScott Long 		u_int8_t *iop_data;
130244f05562SScott Long 		int allxfer_len=0;
1303f1c579b1SScott Long 
130444f05562SScott Long 		acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READ);
130544f05562SScott Long 		pwbuffer=arcmsr_get_iop_wqbuffer(acb);
130644f05562SScott Long 		iop_data=(u_int8_t *)pwbuffer->data;
130744f05562SScott Long 		while((acb->wqbuf_firstindex!=acb->wqbuf_lastindex)
130844f05562SScott Long 			&& (allxfer_len<124)) {
1309ad6d6297SScott Long 			pQbuffer=&acb->wqbuffer[acb->wqbuf_firstindex];
1310f1c579b1SScott Long 			memcpy(iop_data, pQbuffer, 1);
1311ad6d6297SScott Long 			acb->wqbuf_firstindex++;
131244f05562SScott Long 			acb->wqbuf_firstindex %=ARCMSR_MAX_QBUFFER; /*if last index number set it to 0 */
1313f1c579b1SScott Long 			iop_data++;
1314f1c579b1SScott Long 			allxfer_len++;
1315f1c579b1SScott Long 		}
1316f1c579b1SScott Long 		pwbuffer->data_len=allxfer_len;
1317f1c579b1SScott Long 		/*
1318ad6d6297SScott Long 		** push inbound doorbell tell iop driver data write ok
1319ad6d6297SScott Long 		** and wait reply on next hwinterrupt for next Qbuffer post
1320f1c579b1SScott Long 		*/
132144f05562SScott Long 		arcmsr_iop_message_wrote(acb);
1322f1c579b1SScott Long 	}
1323ad6d6297SScott Long 	if(acb->wqbuf_firstindex==acb->wqbuf_lastindex) {
1324ad6d6297SScott Long 		acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_CLEARED;
1325f1c579b1SScott Long 	}
132644f05562SScott Long 	return;
1327f1c579b1SScott Long }
1328*d74001adSXin LI 
1329*d74001adSXin LI static void arcmsr_rescanLun_cb(struct cam_periph *periph, union ccb *ccb)
1330*d74001adSXin LI {
1331*d74001adSXin LI /*
1332*d74001adSXin LI 	if (ccb->ccb_h.status != CAM_REQ_CMP)
1333*d74001adSXin LI 		printf("arcmsr_rescanLun_cb: Rescan Target=%x, lun=%x, failure status=%x\n",ccb->ccb_h.target_id,ccb->ccb_h.target_lun,ccb->ccb_h.status);
1334*d74001adSXin LI 	else
1335*d74001adSXin LI 		printf("arcmsr_rescanLun_cb: Rescan lun successfully!\n");
1336*d74001adSXin LI */
1337*d74001adSXin LI 	xpt_free_path(ccb->ccb_h.path);
1338*d74001adSXin LI 	xpt_free_ccb(ccb);
1339*d74001adSXin LI }
1340*d74001adSXin LI 
1341*d74001adSXin LI static void	arcmsr_rescan_lun(struct AdapterControlBlock *acb, int target, int lun)
1342*d74001adSXin LI {
1343*d74001adSXin LI 	struct cam_path     *path;
1344*d74001adSXin LI 	union ccb           *ccb;
1345*d74001adSXin LI 
1346*d74001adSXin LI 	if ((ccb = (union ccb *)xpt_alloc_ccb_nowait()) == NULL)
1347*d74001adSXin LI  		return;
1348*d74001adSXin LI 	if (xpt_create_path(&path, xpt_periph, cam_sim_path(acb->psim), target, lun) != CAM_REQ_CMP)
1349*d74001adSXin LI 	{
1350*d74001adSXin LI 		xpt_free_ccb(ccb);
1351*d74001adSXin LI 		return;
1352*d74001adSXin LI 	}
1353*d74001adSXin LI /*	printf("arcmsr_rescan_lun: Rescan Target=%x, Lun=%x\n", target, lun); */
1354*d74001adSXin LI 	bzero(ccb, sizeof(union ccb));
1355*d74001adSXin LI 	xpt_setup_ccb(&ccb->ccb_h, path, 5);
1356*d74001adSXin LI 	ccb->ccb_h.func_code = XPT_SCAN_LUN;
1357*d74001adSXin LI 	ccb->ccb_h.cbfcnp = arcmsr_rescanLun_cb;
1358*d74001adSXin LI 	ccb->crcn.flags = CAM_FLAG_NONE;
1359*d74001adSXin LI 	xpt_action(ccb);
1360*d74001adSXin LI 	return;
1361*d74001adSXin LI }
1362*d74001adSXin LI 
1363*d74001adSXin LI 
1364*d74001adSXin LI static void arcmsr_abort_dr_ccbs(struct AdapterControlBlock *acb, int target, int lun)
1365*d74001adSXin LI {
1366*d74001adSXin LI    	struct CommandControlBlock *srb;
1367*d74001adSXin LI 	u_int32_t intmask_org;
1368*d74001adSXin LI    	int i;
1369*d74001adSXin LI 
1370*d74001adSXin LI 	ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
1371*d74001adSXin LI 	/* disable all outbound interrupts */
1372*d74001adSXin LI 	intmask_org = arcmsr_disable_allintr(acb);
1373*d74001adSXin LI 	for (i = 0; i < ARCMSR_MAX_FREESRB_NUM; i++)
1374*d74001adSXin LI 	{
1375*d74001adSXin LI 		srb = acb->psrb_pool[i];
1376*d74001adSXin LI 		if (srb->startdone == ARCMSR_SRB_START)
1377*d74001adSXin LI 		{
1378*d74001adSXin LI            	if((target == srb->pccb->ccb_h.target_id) && (lun == srb->pccb->ccb_h.target_lun))
1379*d74001adSXin LI             {
1380*d74001adSXin LI 		    	srb->startdone = ARCMSR_SRB_ABORTED;
1381*d74001adSXin LI 				srb->pccb->ccb_h.status |= CAM_REQ_ABORTED;
1382*d74001adSXin LI 		    	arcmsr_srb_complete(srb, 1);
1383*d74001adSXin LI        		}
1384*d74001adSXin LI 		}
1385*d74001adSXin LI 	}
1386*d74001adSXin LI 	/* enable outbound Post Queue, outbound doorbell Interrupt */
1387*d74001adSXin LI 	arcmsr_enable_allintr(acb, intmask_org);
1388*d74001adSXin LI 	ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
1389*d74001adSXin LI }
1390*d74001adSXin LI 
1391*d74001adSXin LI 
1392*d74001adSXin LI /*
1393*d74001adSXin LI **************************************************************************
1394*d74001adSXin LI **************************************************************************
1395*d74001adSXin LI */
1396*d74001adSXin LI static void arcmsr_dr_handle(struct AdapterControlBlock *acb) {
1397*d74001adSXin LI 	u_int32_t	devicemap;
1398*d74001adSXin LI 	u_int32_t	target, lun;
1399*d74001adSXin LI     u_int32_t	deviceMapCurrent[4]={0};
1400*d74001adSXin LI     u_int8_t	*pDevMap;
1401*d74001adSXin LI 
1402*d74001adSXin LI 	switch (acb->adapter_type) {
1403*d74001adSXin LI 	case ACB_ADAPTER_TYPE_A:
1404*d74001adSXin LI 			devicemap = offsetof(struct HBA_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
1405*d74001adSXin LI 			for (target= 0; target < 4; target++)
1406*d74001adSXin LI 			{
1407*d74001adSXin LI             	deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], acb->bhandle[0],  devicemap);
1408*d74001adSXin LI             	devicemap += 4;
1409*d74001adSXin LI 			}
1410*d74001adSXin LI 			break;
1411*d74001adSXin LI 
1412*d74001adSXin LI 	case ACB_ADAPTER_TYPE_B:
1413*d74001adSXin LI 			devicemap = offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
1414*d74001adSXin LI 			for (target= 0; target < 4; target++)
1415*d74001adSXin LI 			{
1416*d74001adSXin LI             	deviceMapCurrent[target]=bus_space_read_4(acb->btag[1], acb->bhandle[1],  devicemap);
1417*d74001adSXin LI             	devicemap += 4;
1418*d74001adSXin LI 			}
1419*d74001adSXin LI 			break;
1420*d74001adSXin LI 
1421*d74001adSXin LI 	case ACB_ADAPTER_TYPE_C:
1422*d74001adSXin LI 			devicemap = offsetof(struct HBC_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
1423*d74001adSXin LI 			for (target= 0; target < 4; target++)
1424*d74001adSXin LI 			{
1425*d74001adSXin LI             	deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], acb->bhandle[0],  devicemap);
1426*d74001adSXin LI             	devicemap += 4;
1427*d74001adSXin LI 			}
1428*d74001adSXin LI 			break;
1429*d74001adSXin LI 	}
1430*d74001adSXin LI 		if(acb->acb_flags & ACB_F_BUS_HANG_ON)
1431*d74001adSXin LI 		{
1432*d74001adSXin LI 			acb->acb_flags &= ~ACB_F_BUS_HANG_ON;
1433*d74001adSXin LI 		}
1434*d74001adSXin LI 		/*
1435*d74001adSXin LI 		** adapter posted CONFIG message
1436*d74001adSXin LI 		** copy the new map, note if there are differences with the current map
1437*d74001adSXin LI 		*/
1438*d74001adSXin LI 		pDevMap = (u_int8_t	*)&deviceMapCurrent[0];
1439*d74001adSXin LI 		for (target= 0; target < ARCMSR_MAX_TARGETID - 1; target++)
1440*d74001adSXin LI 		{
1441*d74001adSXin LI 			if (*pDevMap != acb->device_map[target])
1442*d74001adSXin LI 			{
1443*d74001adSXin LI                 u_int8_t difference, bit_check;
1444*d74001adSXin LI 
1445*d74001adSXin LI                 difference= *pDevMap ^ acb->device_map[target];
1446*d74001adSXin LI                 for(lun=0; lun < ARCMSR_MAX_TARGETLUN; lun++)
1447*d74001adSXin LI                 {
1448*d74001adSXin LI                     bit_check=(1 << lun);						/*check bit from 0....31*/
1449*d74001adSXin LI                     if(difference & bit_check)
1450*d74001adSXin LI                     {
1451*d74001adSXin LI                         if(acb->device_map[target] & bit_check)
1452*d74001adSXin LI                         {/* unit departed */
1453*d74001adSXin LI 							printf("arcmsr_dr_handle: Target=%x, lun=%x, GONE!!!\n",target,lun);
1454*d74001adSXin LI  							arcmsr_abort_dr_ccbs(acb, target, lun);
1455*d74001adSXin LI                         	arcmsr_rescan_lun(acb, target, lun);
1456*d74001adSXin LI         					acb->devstate[target][lun] = ARECA_RAID_GONE;
1457*d74001adSXin LI                         }
1458*d74001adSXin LI                         else
1459*d74001adSXin LI                         {/* unit arrived */
1460*d74001adSXin LI 							printf("arcmsr_dr_handle: Target=%x, lun=%x, ARRIVING!!!\n",target,lun);
1461*d74001adSXin LI                         	arcmsr_rescan_lun(acb, target, lun);
1462*d74001adSXin LI         					acb->devstate[target][lun] = ARECA_RAID_GOOD;
1463*d74001adSXin LI                         }
1464*d74001adSXin LI                     }
1465*d74001adSXin LI                 }
1466*d74001adSXin LI /*				printf("arcmsr_dr_handle: acb->device_map[%x]=0x%x, deviceMapCurrent[%x]=%x\n",target,acb->device_map[target],target,*pDevMap); */
1467*d74001adSXin LI 				acb->device_map[target]= *pDevMap;
1468*d74001adSXin LI 			}
1469*d74001adSXin LI 			pDevMap++;
1470*d74001adSXin LI 		}
1471*d74001adSXin LI }
1472*d74001adSXin LI /*
1473*d74001adSXin LI **************************************************************************
1474*d74001adSXin LI **************************************************************************
1475*d74001adSXin LI */
1476*d74001adSXin LI static void arcmsr_hba_message_isr(struct AdapterControlBlock *acb) {
1477*d74001adSXin LI 	u_int32_t outbound_message;
1478*d74001adSXin LI 
1479*d74001adSXin LI 	CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, ARCMSR_MU_OUTBOUND_MESSAGE0_INT);
1480*d74001adSXin LI 	outbound_message = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[0]);
1481*d74001adSXin LI 	if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG)
1482*d74001adSXin LI 		arcmsr_dr_handle( acb );
1483*d74001adSXin LI }
1484*d74001adSXin LI /*
1485*d74001adSXin LI **************************************************************************
1486*d74001adSXin LI **************************************************************************
1487*d74001adSXin LI */
1488*d74001adSXin LI static void arcmsr_hbb_message_isr(struct AdapterControlBlock *acb) {
1489*d74001adSXin LI 	u_int32_t outbound_message;
1490*d74001adSXin LI 
1491*d74001adSXin LI 	/* clear interrupts */
1492*d74001adSXin LI 	CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell, ARCMSR_MESSAGE_INT_CLEAR_PATTERN);
1493*d74001adSXin LI 	outbound_message = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[0]);
1494*d74001adSXin LI 	if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG)
1495*d74001adSXin LI 		arcmsr_dr_handle( acb );
1496*d74001adSXin LI }
1497*d74001adSXin LI /*
1498*d74001adSXin LI **************************************************************************
1499*d74001adSXin LI **************************************************************************
1500*d74001adSXin LI */
1501*d74001adSXin LI static void arcmsr_hbc_message_isr(struct AdapterControlBlock *acb) {
1502*d74001adSXin LI 	u_int32_t outbound_message;
1503*d74001adSXin LI 
1504*d74001adSXin LI 	CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR);
1505*d74001adSXin LI 	outbound_message = CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[0]);
1506*d74001adSXin LI 	if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG)
1507*d74001adSXin LI 		arcmsr_dr_handle( acb );
1508*d74001adSXin LI }
150944f05562SScott Long /*
151044f05562SScott Long **************************************************************************
151144f05562SScott Long **************************************************************************
151244f05562SScott Long */
151344f05562SScott Long static void arcmsr_hba_doorbell_isr(struct AdapterControlBlock *acb)
151444f05562SScott Long {
151544f05562SScott Long 	u_int32_t outbound_doorbell;
151644f05562SScott Long 
151744f05562SScott Long 	/*
151844f05562SScott Long 	*******************************************************************
151944f05562SScott Long 	**  Maybe here we need to check wrqbuffer_lock is lock or not
152044f05562SScott Long 	**  DOORBELL: din! don!
152144f05562SScott Long 	**  check if there are any mail need to pack from firmware
152244f05562SScott Long 	*******************************************************************
152344f05562SScott Long 	*/
152444f05562SScott Long 	outbound_doorbell=CHIP_REG_READ32(HBA_MessageUnit,
152544f05562SScott Long 	0, outbound_doorbell);
152644f05562SScott Long 	CHIP_REG_WRITE32(HBA_MessageUnit,
152744f05562SScott Long 	0, outbound_doorbell, outbound_doorbell); /* clear doorbell interrupt */
152844f05562SScott Long 	if(outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_WRITE_OK) {
152944f05562SScott Long 		arcmsr_iop2drv_data_wrote_handle(acb);
1530ad6d6297SScott Long 	}
153144f05562SScott Long 	if(outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_READ_OK) {
153244f05562SScott Long 		arcmsr_iop2drv_data_read_handle(acb);
153344f05562SScott Long 	}
153444f05562SScott Long 	return;
153544f05562SScott Long }
153644f05562SScott Long /*
153744f05562SScott Long **************************************************************************
153844f05562SScott Long **************************************************************************
153944f05562SScott Long */
1540*d74001adSXin LI static void arcmsr_hbc_doorbell_isr(struct AdapterControlBlock *acb)
1541*d74001adSXin LI {
1542*d74001adSXin LI 	u_int32_t outbound_doorbell;
1543*d74001adSXin LI 
1544*d74001adSXin LI 	/*
1545*d74001adSXin LI 	*******************************************************************
1546*d74001adSXin LI 	**  Maybe here we need to check wrqbuffer_lock is lock or not
1547*d74001adSXin LI 	**  DOORBELL: din! don!
1548*d74001adSXin LI 	**  check if there are any mail need to pack from firmware
1549*d74001adSXin LI 	*******************************************************************
1550*d74001adSXin LI 	*/
1551*d74001adSXin LI 	outbound_doorbell=CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell);
1552*d74001adSXin LI 	CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, outbound_doorbell); /* clear doorbell interrupt */
1553*d74001adSXin LI 	if(outbound_doorbell & ARCMSR_HBCMU_IOP2DRV_DATA_WRITE_OK) {
1554*d74001adSXin LI 		arcmsr_iop2drv_data_wrote_handle(acb);
1555*d74001adSXin LI 	}
1556*d74001adSXin LI 	if(outbound_doorbell & ARCMSR_HBCMU_IOP2DRV_DATA_READ_OK) {
1557*d74001adSXin LI 		arcmsr_iop2drv_data_read_handle(acb);
1558*d74001adSXin LI 	}
1559*d74001adSXin LI 	if(outbound_doorbell & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) {
1560*d74001adSXin LI 		arcmsr_hbc_message_isr(acb);    /* messenger of "driver to iop commands" */
1561*d74001adSXin LI 	}
1562*d74001adSXin LI 	return;
1563*d74001adSXin LI }
1564*d74001adSXin LI /*
1565*d74001adSXin LI **************************************************************************
1566*d74001adSXin LI **************************************************************************
1567*d74001adSXin LI */
156844f05562SScott Long static void arcmsr_hba_postqueue_isr(struct AdapterControlBlock *acb)
156944f05562SScott Long {
157044f05562SScott Long 	u_int32_t flag_srb;
1571*d74001adSXin LI 	u_int16_t error;
157244f05562SScott Long 
1573f1c579b1SScott Long 	/*
1574f1c579b1SScott Long 	*****************************************************************************
1575f1c579b1SScott Long 	**               areca cdb command done
1576f1c579b1SScott Long 	*****************************************************************************
1577f1c579b1SScott Long 	*/
157844f05562SScott Long 	bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap,
157944f05562SScott Long 		BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
158044f05562SScott Long 	while((flag_srb=CHIP_REG_READ32(HBA_MessageUnit,
158144f05562SScott Long 		0, outbound_queueport)) != 0xFFFFFFFF) {
1582f1c579b1SScott Long 		/* check if command done with no error*/
1583*d74001adSXin LI         error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE;
1584*d74001adSXin LI 		arcmsr_drain_donequeue(acb, flag_srb, error);
158544f05562SScott Long 	}	/*drain reply FIFO*/
158644f05562SScott Long 	return;
1587f1c579b1SScott Long }
158844f05562SScott Long /*
158944f05562SScott Long **************************************************************************
159044f05562SScott Long **************************************************************************
159144f05562SScott Long */
159244f05562SScott Long static void arcmsr_hbb_postqueue_isr(struct AdapterControlBlock *acb)
159344f05562SScott Long {
159444f05562SScott Long 	struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu;
159544f05562SScott Long 	u_int32_t flag_srb;
159644f05562SScott Long 	int index;
1597*d74001adSXin LI 	u_int16_t error;
159844f05562SScott Long 
159944f05562SScott Long 	/*
160044f05562SScott Long 	*****************************************************************************
160144f05562SScott Long 	**               areca cdb command done
160244f05562SScott Long 	*****************************************************************************
160344f05562SScott Long 	*/
160444f05562SScott Long 	bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap,
160544f05562SScott Long 		BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
160644f05562SScott Long 	index=phbbmu->doneq_index;
160744f05562SScott Long 	while((flag_srb=phbbmu->done_qbuffer[index]) != 0) {
160844f05562SScott Long 		phbbmu->done_qbuffer[index]=0;
160944f05562SScott Long 		index++;
161044f05562SScott Long 		index %= ARCMSR_MAX_HBB_POSTQUEUE;     /*if last index number set it to 0 */
161144f05562SScott Long 		phbbmu->doneq_index=index;
161244f05562SScott Long 		/* check if command done with no error*/
1613*d74001adSXin LI         error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE;
1614*d74001adSXin LI 		arcmsr_drain_donequeue(acb, flag_srb, error);
1615*d74001adSXin LI 	}	/*drain reply FIFO*/
1616*d74001adSXin LI 	return;
1617*d74001adSXin LI }
1618*d74001adSXin LI /*
1619*d74001adSXin LI **************************************************************************
1620*d74001adSXin LI **************************************************************************
1621*d74001adSXin LI */
1622*d74001adSXin LI static void arcmsr_hbc_postqueue_isr(struct AdapterControlBlock *acb)
1623*d74001adSXin LI {
1624*d74001adSXin LI 	u_int32_t flag_srb,throttling=0;
1625*d74001adSXin LI 	u_int16_t error;
1626*d74001adSXin LI 
1627*d74001adSXin LI 	/*
1628*d74001adSXin LI 	*****************************************************************************
1629*d74001adSXin LI 	**               areca cdb command done
1630*d74001adSXin LI 	*****************************************************************************
1631*d74001adSXin LI 	*/
1632*d74001adSXin LI 	bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
1633*d74001adSXin LI 
1634*d74001adSXin LI 	while(CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) {
1635*d74001adSXin LI 
1636*d74001adSXin LI 		flag_srb=CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_queueport_low);
1637*d74001adSXin LI 		/* check if command done with no error*/
1638*d74001adSXin LI         error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1)?TRUE:FALSE;
1639*d74001adSXin LI 		arcmsr_drain_donequeue(acb, flag_srb, error);
1640*d74001adSXin LI         if(throttling==ARCMSR_HBC_ISR_THROTTLING_LEVEL) {
1641*d74001adSXin LI             CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell,ARCMSR_HBCMU_DRV2IOP_POSTQUEUE_THROTTLING);
1642*d74001adSXin LI             break;
1643*d74001adSXin LI         }
1644*d74001adSXin LI         throttling++;
164544f05562SScott Long 	}	/*drain reply FIFO*/
164644f05562SScott Long 	return;
1647f1c579b1SScott Long }
164844f05562SScott Long /*
164944f05562SScott Long **********************************************************************
165044f05562SScott Long **********************************************************************
165144f05562SScott Long */
165244f05562SScott Long static void arcmsr_handle_hba_isr( struct AdapterControlBlock *acb)
165344f05562SScott Long {
165444f05562SScott Long 	u_int32_t outbound_intstatus;
165544f05562SScott Long 	/*
165644f05562SScott Long 	*********************************************
165744f05562SScott Long 	**   check outbound intstatus
165844f05562SScott Long 	*********************************************
165944f05562SScott Long 	*/
1660*d74001adSXin LI 	outbound_intstatus=CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & acb->outbound_int_enable;
166144f05562SScott Long 	if(!outbound_intstatus) {
166244f05562SScott Long 		/*it must be share irq*/
166344f05562SScott Long 		return;
1664f1c579b1SScott Long 	}
1665*d74001adSXin LI 	CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, outbound_intstatus);/*clear interrupt*/
166644f05562SScott Long 	/* MU doorbell interrupts*/
166744f05562SScott Long 	if(outbound_intstatus & ARCMSR_MU_OUTBOUND_DOORBELL_INT) {
166844f05562SScott Long 		arcmsr_hba_doorbell_isr(acb);
1669f1c579b1SScott Long 	}
167044f05562SScott Long 	/* MU post queue interrupts*/
167144f05562SScott Long 	if(outbound_intstatus & ARCMSR_MU_OUTBOUND_POSTQUEUE_INT) {
167244f05562SScott Long 		arcmsr_hba_postqueue_isr(acb);
167344f05562SScott Long 	}
1674*d74001adSXin LI 	if(outbound_intstatus & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) {
1675*d74001adSXin LI 		arcmsr_hba_message_isr(acb);
1676*d74001adSXin LI 	}
167744f05562SScott Long 	return;
167844f05562SScott Long }
167944f05562SScott Long /*
168044f05562SScott Long **********************************************************************
168144f05562SScott Long **********************************************************************
168244f05562SScott Long */
168344f05562SScott Long static void arcmsr_handle_hbb_isr( struct AdapterControlBlock *acb)
168444f05562SScott Long {
168544f05562SScott Long 	u_int32_t outbound_doorbell;
168644f05562SScott Long 	/*
168744f05562SScott Long 	*********************************************
168844f05562SScott Long 	**   check outbound intstatus
168944f05562SScott Long 	*********************************************
169044f05562SScott Long 	*/
169144f05562SScott Long 	outbound_doorbell=CHIP_REG_READ32(HBB_DOORBELL, 0, iop2drv_doorbell) & acb->outbound_int_enable;
169244f05562SScott Long 	if(!outbound_doorbell) {
169344f05562SScott Long 		/*it must be share irq*/
169444f05562SScott Long 		return;
169544f05562SScott Long 	}
169644f05562SScott Long 	CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell, ~outbound_doorbell); /* clear doorbell interrupt */
169744f05562SScott Long 	CHIP_REG_READ32(HBB_DOORBELL, 0, iop2drv_doorbell);
169844f05562SScott Long 	CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT);
169944f05562SScott Long 	/* MU ioctl transfer doorbell interrupts*/
170044f05562SScott Long 	if(outbound_doorbell & ARCMSR_IOP2DRV_DATA_WRITE_OK) {
170144f05562SScott Long 		arcmsr_iop2drv_data_wrote_handle(acb);
170244f05562SScott Long 	}
170344f05562SScott Long 	if(outbound_doorbell & ARCMSR_IOP2DRV_DATA_READ_OK) {
170444f05562SScott Long 		arcmsr_iop2drv_data_read_handle(acb);
170544f05562SScott Long 	}
170644f05562SScott Long 	/* MU post queue interrupts*/
170744f05562SScott Long 	if(outbound_doorbell & ARCMSR_IOP2DRV_CDB_DONE) {
170844f05562SScott Long 		arcmsr_hbb_postqueue_isr(acb);
170944f05562SScott Long 	}
1710*d74001adSXin LI 	if(outbound_doorbell & ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) {
1711*d74001adSXin LI 		arcmsr_hbb_message_isr(acb);
1712*d74001adSXin LI 	}
1713*d74001adSXin LI 	return;
1714*d74001adSXin LI }
1715*d74001adSXin LI /*
1716*d74001adSXin LI **********************************************************************
1717*d74001adSXin LI **********************************************************************
1718*d74001adSXin LI */
1719*d74001adSXin LI static void arcmsr_handle_hbc_isr( struct AdapterControlBlock *acb)
1720*d74001adSXin LI {
1721*d74001adSXin LI 	u_int32_t host_interrupt_status;
1722*d74001adSXin LI 	/*
1723*d74001adSXin LI 	*********************************************
1724*d74001adSXin LI 	**   check outbound intstatus
1725*d74001adSXin LI 	*********************************************
1726*d74001adSXin LI 	*/
1727*d74001adSXin LI 	host_interrupt_status=CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status);
1728*d74001adSXin LI 	if(!host_interrupt_status) {
1729*d74001adSXin LI 		/*it must be share irq*/
1730*d74001adSXin LI 		return;
1731*d74001adSXin LI 	}
1732*d74001adSXin LI 	/* MU doorbell interrupts*/
1733*d74001adSXin LI 	if(host_interrupt_status & ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR) {
1734*d74001adSXin LI 		arcmsr_hbc_doorbell_isr(acb);
1735*d74001adSXin LI 	}
1736*d74001adSXin LI 	/* MU post queue interrupts*/
1737*d74001adSXin LI 	if(host_interrupt_status & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) {
1738*d74001adSXin LI 		arcmsr_hbc_postqueue_isr(acb);
1739*d74001adSXin LI 	}
174044f05562SScott Long 	return;
174144f05562SScott Long }
174244f05562SScott Long /*
174344f05562SScott Long ******************************************************************************
174444f05562SScott Long ******************************************************************************
174544f05562SScott Long */
174644f05562SScott Long static void arcmsr_interrupt(struct AdapterControlBlock *acb)
174744f05562SScott Long {
174844f05562SScott Long 	switch (acb->adapter_type) {
174944f05562SScott Long 	case ACB_ADAPTER_TYPE_A:
175044f05562SScott Long 		arcmsr_handle_hba_isr(acb);
1751f1c579b1SScott Long 		break;
175244f05562SScott Long 	case ACB_ADAPTER_TYPE_B:
175344f05562SScott Long 		arcmsr_handle_hbb_isr(acb);
1754f1c579b1SScott Long 		break;
1755*d74001adSXin LI 	case ACB_ADAPTER_TYPE_C:
1756*d74001adSXin LI 		arcmsr_handle_hbc_isr(acb);
1757*d74001adSXin LI 		break;
1758f1c579b1SScott Long 	default:
175944f05562SScott Long 		printf("arcmsr%d: interrupt service,"
176044f05562SScott Long 		" unknow adapter type =%d\n", acb->pci_unit, acb->adapter_type);
1761f1c579b1SScott Long 		break;
1762f1c579b1SScott Long 	}
1763f1c579b1SScott Long 	return;
1764f1c579b1SScott Long }
1765f1c579b1SScott Long /*
1766*d74001adSXin LI **********************************************************************
1767*d74001adSXin LI **********************************************************************
1768*d74001adSXin LI */
1769*d74001adSXin LI static void arcmsr_intr_handler(void *arg)
1770*d74001adSXin LI {
1771*d74001adSXin LI 	struct AdapterControlBlock *acb=(struct AdapterControlBlock *)arg;
1772*d74001adSXin LI 
1773*d74001adSXin LI 	ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
1774*d74001adSXin LI 	arcmsr_interrupt(acb);
1775*d74001adSXin LI 	ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
1776*d74001adSXin LI }
1777*d74001adSXin LI /*
1778*d74001adSXin LI ******************************************************************************
1779*d74001adSXin LI ******************************************************************************
1780*d74001adSXin LI */
1781*d74001adSXin LI static void	arcmsr_polling_devmap(void* arg)
1782*d74001adSXin LI {
1783*d74001adSXin LI 	struct AdapterControlBlock *acb = (struct AdapterControlBlock *)arg;
1784*d74001adSXin LI 	switch (acb->adapter_type) {
1785*d74001adSXin LI     	case ACB_ADAPTER_TYPE_A:
1786*d74001adSXin LI 			CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG);
1787*d74001adSXin LI 	    	break;
1788*d74001adSXin LI 
1789*d74001adSXin LI     	case ACB_ADAPTER_TYPE_B:
1790*d74001adSXin LI 			CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_MESSAGE_GET_CONFIG);
1791*d74001adSXin LI 	    	break;
1792*d74001adSXin LI 
1793*d74001adSXin LI     	case ACB_ADAPTER_TYPE_C:
1794*d74001adSXin LI 			CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG);
1795*d74001adSXin LI 			CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE);
1796*d74001adSXin LI 	    	break;
1797*d74001adSXin LI 	}
1798*d74001adSXin LI 
1799*d74001adSXin LI 	if((acb->acb_flags & ACB_F_SCSISTOPADAPTER) == 0)
1800*d74001adSXin LI 	{
1801*d74001adSXin LI 		callout_reset(&acb->devmap_callout, 5 * hz, arcmsr_polling_devmap, acb);	/* polling per 5 seconds */
1802*d74001adSXin LI 	}
1803*d74001adSXin LI }
1804*d74001adSXin LI 
1805*d74001adSXin LI /*
1806ad6d6297SScott Long *******************************************************************************
1807ad6d6297SScott Long **
1808ad6d6297SScott Long *******************************************************************************
1809ad6d6297SScott Long */
1810ad6d6297SScott Long static void arcmsr_iop_parking(struct AdapterControlBlock *acb)
1811ad6d6297SScott Long {
1812*d74001adSXin LI 	u_int32_t intmask_org;
1813*d74001adSXin LI 
1814ad6d6297SScott Long 	if(acb!=NULL) {
1815ad6d6297SScott Long 		/* stop adapter background rebuild */
1816ad6d6297SScott Long 		if(acb->acb_flags & ACB_F_MSG_START_BGRB) {
1817*d74001adSXin LI 			intmask_org = arcmsr_disable_allintr(acb);
1818ad6d6297SScott Long 			arcmsr_stop_adapter_bgrb(acb);
1819ad6d6297SScott Long 			arcmsr_flush_adapter_cache(acb);
1820*d74001adSXin LI 			arcmsr_enable_allintr(acb, intmask_org);
1821ad6d6297SScott Long 		}
1822ad6d6297SScott Long 	}
1823ad6d6297SScott Long }
1824ad6d6297SScott Long /*
1825f1c579b1SScott Long ***********************************************************************
1826f1c579b1SScott Long **
1827f1c579b1SScott Long ************************************************************************
1828f1c579b1SScott Long */
1829ad6d6297SScott Long u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t ioctl_cmd, caddr_t arg)
1830f1c579b1SScott Long {
1831ad6d6297SScott Long 	struct CMD_MESSAGE_FIELD * pcmdmessagefld;
1832ad6d6297SScott Long 	u_int32_t retvalue=EINVAL;
1833f1c579b1SScott Long 
1834ad6d6297SScott Long 	pcmdmessagefld=(struct CMD_MESSAGE_FIELD *) arg;
1835ad6d6297SScott Long 	if(memcmp(pcmdmessagefld->cmdmessage.Signature, "ARCMSR", 6)!=0) {
1836ad6d6297SScott Long 		return retvalue;
1837f1c579b1SScott Long 	}
1838ad6d6297SScott Long 	ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
1839ad6d6297SScott Long 	switch(ioctl_cmd) {
1840ad6d6297SScott Long 	case ARCMSR_MESSAGE_READ_RQBUFFER: {
1841ad6d6297SScott Long 			u_int8_t * pQbuffer;
1842ad6d6297SScott Long 			u_int8_t * ptmpQbuffer=pcmdmessagefld->messagedatabuffer;
1843ad6d6297SScott Long 			u_int32_t allxfer_len=0;
1844f1c579b1SScott Long 
184544f05562SScott Long 			while((acb->rqbuf_firstindex!=acb->rqbuf_lastindex)
184644f05562SScott Long 				&& (allxfer_len<1031)) {
1847f1c579b1SScott Long 				/*copy READ QBUFFER to srb*/
1848ad6d6297SScott Long 				pQbuffer= &acb->rqbuffer[acb->rqbuf_firstindex];
1849f1c579b1SScott Long 				memcpy(ptmpQbuffer, pQbuffer, 1);
1850ad6d6297SScott Long 				acb->rqbuf_firstindex++;
1851ad6d6297SScott Long 				acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER;
1852ad6d6297SScott Long 				/*if last index number set it to 0 */
1853f1c579b1SScott Long 				ptmpQbuffer++;
1854f1c579b1SScott Long 				allxfer_len++;
1855f1c579b1SScott Long 			}
1856ad6d6297SScott Long 			if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
185744f05562SScott Long 				struct QBUFFER * prbuffer;
185844f05562SScott Long 				u_int8_t * iop_data;
1859ad6d6297SScott Long 				u_int32_t iop_len;
1860f1c579b1SScott Long 
1861ad6d6297SScott Long 				acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
186244f05562SScott Long 				prbuffer=arcmsr_get_iop_rqbuffer(acb);
186344f05562SScott Long 				iop_data=(u_int8_t *)prbuffer->data;
1864ad6d6297SScott Long 				iop_len=(u_int32_t)prbuffer->data_len;
1865f1c579b1SScott Long 				/*this iop data does no chance to make me overflow again here, so just do it*/
1866ad6d6297SScott Long 				while(iop_len>0) {
1867ad6d6297SScott Long 					pQbuffer= &acb->rqbuffer[acb->rqbuf_lastindex];
1868f1c579b1SScott Long 					memcpy(pQbuffer, iop_data, 1);
1869ad6d6297SScott Long 					acb->rqbuf_lastindex++;
1870ad6d6297SScott Long 					acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER;
1871ad6d6297SScott Long 					/*if last index number set it to 0 */
1872f1c579b1SScott Long 					iop_data++;
1873f1c579b1SScott Long 					iop_len--;
1874f1c579b1SScott Long 				}
187544f05562SScott Long 				arcmsr_iop_message_read(acb);
187644f05562SScott Long 				/*signature, let IOP know data has been readed */
1877f1c579b1SScott Long 			}
1878ad6d6297SScott Long 			pcmdmessagefld->cmdmessage.Length=allxfer_len;
1879ad6d6297SScott Long 			pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK;
1880ad6d6297SScott Long 			retvalue=ARCMSR_MESSAGE_SUCCESS;
1881f1c579b1SScott Long 		}
1882f1c579b1SScott Long 		break;
1883ad6d6297SScott Long 	case ARCMSR_MESSAGE_WRITE_WQBUFFER: {
1884ad6d6297SScott Long 			u_int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex;
1885ad6d6297SScott Long 			u_int8_t * pQbuffer;
1886ad6d6297SScott Long 			u_int8_t * ptmpuserbuffer=pcmdmessagefld->messagedatabuffer;
1887f1c579b1SScott Long 
1888ad6d6297SScott Long 			user_len=pcmdmessagefld->cmdmessage.Length;
1889f1c579b1SScott Long 			/*check if data xfer length of this request will overflow my array qbuffer */
1890ad6d6297SScott Long 			wqbuf_lastindex=acb->wqbuf_lastindex;
1891ad6d6297SScott Long 			wqbuf_firstindex=acb->wqbuf_firstindex;
1892ad6d6297SScott Long 			if(wqbuf_lastindex!=wqbuf_firstindex) {
189344f05562SScott Long 				arcmsr_post_ioctldata2iop(acb);
1894ad6d6297SScott Long 				pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_ERROR;
1895ad6d6297SScott Long 			} else {
1896f1c579b1SScott Long 				my_empty_len=(wqbuf_firstindex-wqbuf_lastindex-1)&(ARCMSR_MAX_QBUFFER-1);
1897ad6d6297SScott Long 				if(my_empty_len>=user_len) {
1898ad6d6297SScott Long 					while(user_len>0) {
1899f1c579b1SScott Long 						/*copy srb data to wqbuffer*/
1900ad6d6297SScott Long 						pQbuffer= &acb->wqbuffer[acb->wqbuf_lastindex];
1901f1c579b1SScott Long 						memcpy(pQbuffer, ptmpuserbuffer, 1);
1902ad6d6297SScott Long 						acb->wqbuf_lastindex++;
1903ad6d6297SScott Long 						acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER;
1904ad6d6297SScott Long 						/*if last index number set it to 0 */
1905f1c579b1SScott Long 						ptmpuserbuffer++;
1906f1c579b1SScott Long 						user_len--;
1907f1c579b1SScott Long 					}
1908f1c579b1SScott Long 					/*post fist Qbuffer*/
1909ad6d6297SScott Long 					if(acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) {
1910ad6d6297SScott Long 						acb->acb_flags &=~ACB_F_MESSAGE_WQBUFFER_CLEARED;
191144f05562SScott Long 						arcmsr_post_ioctldata2iop(acb);
1912f1c579b1SScott Long 					}
1913ad6d6297SScott Long 					pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK;
1914ad6d6297SScott Long 				} else {
1915ad6d6297SScott Long 					pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_ERROR;
1916f1c579b1SScott Long 				}
1917f1c579b1SScott Long 			}
1918ad6d6297SScott Long 			retvalue=ARCMSR_MESSAGE_SUCCESS;
1919f1c579b1SScott Long 		}
1920f1c579b1SScott Long 		break;
1921ad6d6297SScott Long 	case ARCMSR_MESSAGE_CLEAR_RQBUFFER: {
1922ad6d6297SScott Long 			u_int8_t * pQbuffer=acb->rqbuffer;
1923ad6d6297SScott Long 
1924ad6d6297SScott Long 			if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
1925ad6d6297SScott Long 				acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
192644f05562SScott Long 				arcmsr_iop_message_read(acb);
192744f05562SScott Long 				/*signature, let IOP know data has been readed */
1928f1c579b1SScott Long 			}
1929ad6d6297SScott Long 			acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED;
1930ad6d6297SScott Long 			acb->rqbuf_firstindex=0;
1931ad6d6297SScott Long 			acb->rqbuf_lastindex=0;
1932f1c579b1SScott Long 			memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER);
1933ad6d6297SScott Long 			pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK;
1934ad6d6297SScott Long 			retvalue=ARCMSR_MESSAGE_SUCCESS;
1935f1c579b1SScott Long 		}
1936f1c579b1SScott Long 		break;
1937ad6d6297SScott Long 	case ARCMSR_MESSAGE_CLEAR_WQBUFFER:
1938f1c579b1SScott Long 		{
1939ad6d6297SScott Long 			u_int8_t * pQbuffer=acb->wqbuffer;
1940f1c579b1SScott Long 
1941ad6d6297SScott Long 			if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
1942ad6d6297SScott Long 				acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
194344f05562SScott Long                 arcmsr_iop_message_read(acb);
194444f05562SScott Long 				/*signature, let IOP know data has been readed */
1945f1c579b1SScott Long 			}
194644f05562SScott Long 			acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED|ACB_F_MESSAGE_WQBUFFER_READ);
1947ad6d6297SScott Long 			acb->wqbuf_firstindex=0;
1948ad6d6297SScott Long 			acb->wqbuf_lastindex=0;
1949f1c579b1SScott Long 			memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER);
1950ad6d6297SScott Long 			pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK;
1951ad6d6297SScott Long 			retvalue=ARCMSR_MESSAGE_SUCCESS;
1952f1c579b1SScott Long 		}
1953f1c579b1SScott Long 		break;
1954ad6d6297SScott Long 	case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER: {
1955ad6d6297SScott Long 			u_int8_t * pQbuffer;
1956f1c579b1SScott Long 
1957ad6d6297SScott Long 			if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
1958ad6d6297SScott Long 				acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
195944f05562SScott Long                 arcmsr_iop_message_read(acb);
196044f05562SScott Long 				/*signature, let IOP know data has been readed */
1961f1c579b1SScott Long 			}
1962ad6d6297SScott Long 			acb->acb_flags  |= (ACB_F_MESSAGE_WQBUFFER_CLEARED
1963ad6d6297SScott Long 					|ACB_F_MESSAGE_RQBUFFER_CLEARED
196444f05562SScott Long 					|ACB_F_MESSAGE_WQBUFFER_READ);
1965ad6d6297SScott Long 			acb->rqbuf_firstindex=0;
1966ad6d6297SScott Long 			acb->rqbuf_lastindex=0;
1967ad6d6297SScott Long 			acb->wqbuf_firstindex=0;
1968ad6d6297SScott Long 			acb->wqbuf_lastindex=0;
1969ad6d6297SScott Long 			pQbuffer=acb->rqbuffer;
1970ad6d6297SScott Long 			memset(pQbuffer, 0, sizeof(struct QBUFFER));
1971ad6d6297SScott Long 			pQbuffer=acb->wqbuffer;
1972ad6d6297SScott Long 			memset(pQbuffer, 0, sizeof(struct QBUFFER));
1973ad6d6297SScott Long 			pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK;
1974ad6d6297SScott Long 			retvalue=ARCMSR_MESSAGE_SUCCESS;
1975f1c579b1SScott Long 		}
1976f1c579b1SScott Long 		break;
1977ad6d6297SScott Long 	case ARCMSR_MESSAGE_REQUEST_RETURNCODE_3F: {
1978ad6d6297SScott Long 			pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_3F;
1979ad6d6297SScott Long 			retvalue=ARCMSR_MESSAGE_SUCCESS;
1980f1c579b1SScott Long 		}
1981f1c579b1SScott Long 		break;
1982ad6d6297SScott Long 	case ARCMSR_MESSAGE_SAY_HELLO: {
1983ad6d6297SScott Long 			u_int8_t * hello_string="Hello! I am ARCMSR";
1984ad6d6297SScott Long 			u_int8_t * puserbuffer=(u_int8_t *)pcmdmessagefld->messagedatabuffer;
1985f1c579b1SScott Long 
1986ad6d6297SScott Long 			if(memcpy(puserbuffer, hello_string, (int16_t)strlen(hello_string))) {
1987ad6d6297SScott Long 				pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_ERROR;
1988ad6d6297SScott Long 				ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
1989f1c579b1SScott Long 				return ENOIOCTL;
1990f1c579b1SScott Long 			}
1991ad6d6297SScott Long 			pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK;
1992ad6d6297SScott Long 			retvalue=ARCMSR_MESSAGE_SUCCESS;
1993ad6d6297SScott Long 		}
1994ad6d6297SScott Long 		break;
1995ad6d6297SScott Long 	case ARCMSR_MESSAGE_SAY_GOODBYE: {
1996ad6d6297SScott Long 			arcmsr_iop_parking(acb);
1997ad6d6297SScott Long 			retvalue=ARCMSR_MESSAGE_SUCCESS;
1998ad6d6297SScott Long 		}
1999ad6d6297SScott Long 		break;
2000ad6d6297SScott Long 	case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE: {
2001ad6d6297SScott Long 			arcmsr_flush_adapter_cache(acb);
2002ad6d6297SScott Long 			retvalue=ARCMSR_MESSAGE_SUCCESS;
2003f1c579b1SScott Long 		}
2004f1c579b1SScott Long 		break;
2005f1c579b1SScott Long 	}
2006ad6d6297SScott Long 	ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
2007ad6d6297SScott Long 	return retvalue;
2008f1c579b1SScott Long }
2009f1c579b1SScott Long /*
2010f1c579b1SScott Long **************************************************************************
2011f1c579b1SScott Long **************************************************************************
2012f1c579b1SScott Long */
2013ad6d6297SScott Long struct CommandControlBlock * arcmsr_get_freesrb(struct AdapterControlBlock *acb)
2014f1c579b1SScott Long {
2015ad6d6297SScott Long 	struct CommandControlBlock *srb=NULL;
2016ad6d6297SScott Long 	u_int32_t workingsrb_startindex, workingsrb_doneindex;
2017f1c579b1SScott Long 
2018579ec1a5SScott Long #if __FreeBSD_version < 700025
2019579ec1a5SScott Long 	ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
2020579ec1a5SScott Long #endif
2021ad6d6297SScott Long 	workingsrb_doneindex=acb->workingsrb_doneindex;
2022ad6d6297SScott Long 	workingsrb_startindex=acb->workingsrb_startindex;
2023ad6d6297SScott Long 	srb=acb->srbworkingQ[workingsrb_startindex];
2024ad6d6297SScott Long 	workingsrb_startindex++;
2025ad6d6297SScott Long 	workingsrb_startindex %= ARCMSR_MAX_FREESRB_NUM;
2026ad6d6297SScott Long 	if(workingsrb_doneindex!=workingsrb_startindex) {
2027ad6d6297SScott Long 		acb->workingsrb_startindex=workingsrb_startindex;
2028ad6d6297SScott Long 	} else {
2029ad6d6297SScott Long 		srb=NULL;
2030ad6d6297SScott Long 	}
2031579ec1a5SScott Long #if __FreeBSD_version < 700025
2032579ec1a5SScott Long 	ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
2033579ec1a5SScott Long #endif
2034ad6d6297SScott Long 	return(srb);
2035ad6d6297SScott Long }
2036ad6d6297SScott Long /*
2037ad6d6297SScott Long **************************************************************************
2038ad6d6297SScott Long **************************************************************************
2039ad6d6297SScott Long */
2040ad6d6297SScott Long static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb * pccb)
2041ad6d6297SScott Long {
2042ad6d6297SScott Long 	struct CMD_MESSAGE_FIELD * pcmdmessagefld;
2043ad6d6297SScott Long 	int retvalue = 0, transfer_len = 0;
2044ad6d6297SScott Long 	char *buffer;
204544f05562SScott Long 	u_int32_t controlcode = (u_int32_t ) pccb->csio.cdb_io.cdb_bytes[5] << 24 |
204644f05562SScott Long 				(u_int32_t ) pccb->csio.cdb_io.cdb_bytes[6] << 16 |
204744f05562SScott Long 				(u_int32_t ) pccb->csio.cdb_io.cdb_bytes[7] << 8  |
204844f05562SScott Long 				(u_int32_t ) pccb->csio.cdb_io.cdb_bytes[8];
2049ad6d6297SScott Long 					/* 4 bytes: Areca io control code */
2050ad6d6297SScott Long 	if((pccb->ccb_h.flags & CAM_SCATTER_VALID) == 0) {
2051ad6d6297SScott Long 		buffer = pccb->csio.data_ptr;
2052ad6d6297SScott Long 		transfer_len = pccb->csio.dxfer_len;
2053ad6d6297SScott Long 	} else {
2054ad6d6297SScott Long 		retvalue = ARCMSR_MESSAGE_FAIL;
2055ad6d6297SScott Long 		goto message_out;
2056ad6d6297SScott Long 	}
2057ad6d6297SScott Long 	if (transfer_len > sizeof(struct CMD_MESSAGE_FIELD)) {
2058ad6d6297SScott Long 		retvalue = ARCMSR_MESSAGE_FAIL;
2059ad6d6297SScott Long 		goto message_out;
2060ad6d6297SScott Long 	}
2061ad6d6297SScott Long 	pcmdmessagefld = (struct CMD_MESSAGE_FIELD *) buffer;
2062ad6d6297SScott Long 	switch(controlcode) {
2063ad6d6297SScott Long 	case ARCMSR_MESSAGE_READ_RQBUFFER: {
2064ad6d6297SScott Long 			u_int8_t *pQbuffer;
2065ad6d6297SScott Long 			u_int8_t *ptmpQbuffer=pcmdmessagefld->messagedatabuffer;
2066ad6d6297SScott Long 			int32_t allxfer_len = 0;
2067f1c579b1SScott Long 
2068ad6d6297SScott Long 			while ((acb->rqbuf_firstindex != acb->rqbuf_lastindex)
2069ad6d6297SScott Long 				&& (allxfer_len < 1031)) {
2070ad6d6297SScott Long 				pQbuffer = &acb->rqbuffer[acb->rqbuf_firstindex];
2071ad6d6297SScott Long 				memcpy(ptmpQbuffer, pQbuffer, 1);
2072ad6d6297SScott Long 				acb->rqbuf_firstindex++;
2073ad6d6297SScott Long 				acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER;
2074ad6d6297SScott Long 				ptmpQbuffer++;
2075ad6d6297SScott Long 				allxfer_len++;
2076f1c579b1SScott Long 			}
2077ad6d6297SScott Long 			if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
207844f05562SScott Long 				struct QBUFFER  *prbuffer;
207944f05562SScott Long 				u_int8_t  *iop_data;
2080ad6d6297SScott Long 				int32_t iop_len;
2081ad6d6297SScott Long 
2082ad6d6297SScott Long 				acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
208344f05562SScott Long 				prbuffer=arcmsr_get_iop_rqbuffer(acb);
208444f05562SScott Long 				iop_data = (u_int8_t *)prbuffer->data;
2085ad6d6297SScott Long 				iop_len =(u_int32_t)prbuffer->data_len;
2086ad6d6297SScott Long 				while (iop_len > 0) {
2087ad6d6297SScott Long 			        pQbuffer= &acb->rqbuffer[acb->rqbuf_lastindex];
2088ad6d6297SScott Long 					memcpy(pQbuffer, iop_data, 1);
2089ad6d6297SScott Long 					acb->rqbuf_lastindex++;
2090ad6d6297SScott Long 					acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER;
2091ad6d6297SScott Long 					iop_data++;
2092ad6d6297SScott Long 					iop_len--;
2093f1c579b1SScott Long 				}
209444f05562SScott Long 				arcmsr_iop_message_read(acb);
2095ad6d6297SScott Long 			}
2096ad6d6297SScott Long 			pcmdmessagefld->cmdmessage.Length = allxfer_len;
2097ad6d6297SScott Long 			pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
2098ad6d6297SScott Long 			retvalue=ARCMSR_MESSAGE_SUCCESS;
2099ad6d6297SScott Long 		}
2100ad6d6297SScott Long 		break;
2101ad6d6297SScott Long 	case ARCMSR_MESSAGE_WRITE_WQBUFFER: {
2102ad6d6297SScott Long 			int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex;
2103ad6d6297SScott Long 			u_int8_t *pQbuffer;
2104ad6d6297SScott Long 			u_int8_t *ptmpuserbuffer=pcmdmessagefld->messagedatabuffer;
2105ad6d6297SScott Long 
2106ad6d6297SScott Long 			user_len = pcmdmessagefld->cmdmessage.Length;
2107ad6d6297SScott Long 			wqbuf_lastindex = acb->wqbuf_lastindex;
2108ad6d6297SScott Long 			wqbuf_firstindex = acb->wqbuf_firstindex;
2109ad6d6297SScott Long 			if (wqbuf_lastindex != wqbuf_firstindex) {
211044f05562SScott Long 				arcmsr_post_ioctldata2iop(acb);
2111ad6d6297SScott Long 				/* has error report sensedata */
2112ad6d6297SScott Long 			    if(&pccb->csio.sense_data) {
2113ad6d6297SScott Long 				((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70);
2114ad6d6297SScott Long 				/* Valid,ErrorCode */
2115ad6d6297SScott Long 				((u_int8_t *)&pccb->csio.sense_data)[2] = 0x05;
2116ad6d6297SScott Long 				/* FileMark,EndOfMedia,IncorrectLength,Reserved,SenseKey */
2117ad6d6297SScott Long 				((u_int8_t *)&pccb->csio.sense_data)[7] = 0x0A;
2118ad6d6297SScott Long 				/* AdditionalSenseLength */
2119ad6d6297SScott Long 				((u_int8_t *)&pccb->csio.sense_data)[12] = 0x20;
2120ad6d6297SScott Long 				/* AdditionalSenseCode */
2121ad6d6297SScott Long 				}
2122ad6d6297SScott Long 				retvalue = ARCMSR_MESSAGE_FAIL;
2123ad6d6297SScott Long 			} else {
2124ad6d6297SScott Long 				my_empty_len = (wqbuf_firstindex-wqbuf_lastindex - 1)
2125ad6d6297SScott Long 						&(ARCMSR_MAX_QBUFFER - 1);
2126ad6d6297SScott Long 				if (my_empty_len >= user_len) {
2127ad6d6297SScott Long 					while (user_len > 0) {
2128ad6d6297SScott Long 						pQbuffer = &acb->wqbuffer[acb->wqbuf_lastindex];
2129ad6d6297SScott Long 						memcpy(pQbuffer, ptmpuserbuffer, 1);
2130ad6d6297SScott Long 						acb->wqbuf_lastindex++;
2131ad6d6297SScott Long 						acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER;
2132ad6d6297SScott Long 						ptmpuserbuffer++;
2133ad6d6297SScott Long 						user_len--;
2134ad6d6297SScott Long 					}
2135ad6d6297SScott Long 					if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) {
2136ad6d6297SScott Long 						acb->acb_flags &=
2137ad6d6297SScott Long 						~ACB_F_MESSAGE_WQBUFFER_CLEARED;
213844f05562SScott Long 						arcmsr_post_ioctldata2iop(acb);
2139ad6d6297SScott Long 					}
2140ad6d6297SScott Long 				} else {
2141ad6d6297SScott Long 					/* has error report sensedata */
2142ad6d6297SScott Long 					if(&pccb->csio.sense_data) {
2143ad6d6297SScott Long 					((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70);
2144ad6d6297SScott Long 					/* Valid,ErrorCode */
2145ad6d6297SScott Long 					((u_int8_t *)&pccb->csio.sense_data)[2] = 0x05;
2146ad6d6297SScott Long 					/* FileMark,EndOfMedia,IncorrectLength,Reserved,SenseKey */
2147ad6d6297SScott Long 					((u_int8_t *)&pccb->csio.sense_data)[7] = 0x0A;
2148ad6d6297SScott Long 					/* AdditionalSenseLength */
2149ad6d6297SScott Long 					((u_int8_t *)&pccb->csio.sense_data)[12] = 0x20;
2150ad6d6297SScott Long 					/* AdditionalSenseCode */
2151ad6d6297SScott Long 					}
2152ad6d6297SScott Long 					retvalue = ARCMSR_MESSAGE_FAIL;
2153ad6d6297SScott Long 				}
2154ad6d6297SScott Long 			}
2155ad6d6297SScott Long 		}
2156ad6d6297SScott Long 		break;
2157ad6d6297SScott Long 	case ARCMSR_MESSAGE_CLEAR_RQBUFFER: {
2158ad6d6297SScott Long 			u_int8_t *pQbuffer = acb->rqbuffer;
2159ad6d6297SScott Long 
2160ad6d6297SScott Long 			if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
2161ad6d6297SScott Long 				acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
216244f05562SScott Long 				arcmsr_iop_message_read(acb);
2163ad6d6297SScott Long 			}
2164ad6d6297SScott Long 			acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED;
2165ad6d6297SScott Long 			acb->rqbuf_firstindex = 0;
2166ad6d6297SScott Long 			acb->rqbuf_lastindex = 0;
2167ad6d6297SScott Long 			memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER);
2168ad6d6297SScott Long 			pcmdmessagefld->cmdmessage.ReturnCode =
2169ad6d6297SScott Long 			ARCMSR_MESSAGE_RETURNCODE_OK;
2170ad6d6297SScott Long 		}
2171ad6d6297SScott Long 		break;
2172ad6d6297SScott Long 	case ARCMSR_MESSAGE_CLEAR_WQBUFFER: {
2173ad6d6297SScott Long 			u_int8_t *pQbuffer = acb->wqbuffer;
2174ad6d6297SScott Long 
2175ad6d6297SScott Long 			if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
2176ad6d6297SScott Long 				acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
217744f05562SScott Long 				arcmsr_iop_message_read(acb);
2178ad6d6297SScott Long 			}
2179ad6d6297SScott Long 			acb->acb_flags |=
2180ad6d6297SScott Long 				(ACB_F_MESSAGE_WQBUFFER_CLEARED |
218144f05562SScott Long 					ACB_F_MESSAGE_WQBUFFER_READ);
2182ad6d6297SScott Long 			acb->wqbuf_firstindex = 0;
2183ad6d6297SScott Long 			acb->wqbuf_lastindex = 0;
2184ad6d6297SScott Long 			memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER);
2185ad6d6297SScott Long 			pcmdmessagefld->cmdmessage.ReturnCode =
2186ad6d6297SScott Long 				ARCMSR_MESSAGE_RETURNCODE_OK;
2187ad6d6297SScott Long 		}
2188ad6d6297SScott Long 		break;
2189ad6d6297SScott Long 	case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER: {
2190ad6d6297SScott Long 			u_int8_t *pQbuffer;
2191ad6d6297SScott Long 
2192ad6d6297SScott Long 			if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
2193ad6d6297SScott Long 				acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
219444f05562SScott Long 				arcmsr_iop_message_read(acb);
2195ad6d6297SScott Long 			}
2196ad6d6297SScott Long 			acb->acb_flags |=
2197ad6d6297SScott Long 				(ACB_F_MESSAGE_WQBUFFER_CLEARED
2198ad6d6297SScott Long 				| ACB_F_MESSAGE_RQBUFFER_CLEARED
219944f05562SScott Long 				| ACB_F_MESSAGE_WQBUFFER_READ);
2200ad6d6297SScott Long 			acb->rqbuf_firstindex = 0;
2201ad6d6297SScott Long 			acb->rqbuf_lastindex = 0;
2202ad6d6297SScott Long 			acb->wqbuf_firstindex = 0;
2203ad6d6297SScott Long 			acb->wqbuf_lastindex = 0;
2204ad6d6297SScott Long 			pQbuffer = acb->rqbuffer;
2205ad6d6297SScott Long 			memset(pQbuffer, 0, sizeof (struct QBUFFER));
2206ad6d6297SScott Long 			pQbuffer = acb->wqbuffer;
2207ad6d6297SScott Long 			memset(pQbuffer, 0, sizeof (struct QBUFFER));
2208ad6d6297SScott Long 			pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
2209ad6d6297SScott Long 		}
2210ad6d6297SScott Long 		break;
2211ad6d6297SScott Long 	case ARCMSR_MESSAGE_REQUEST_RETURNCODE_3F: {
2212ad6d6297SScott Long 			pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_3F;
2213ad6d6297SScott Long 		}
2214ad6d6297SScott Long 		break;
2215ad6d6297SScott Long 	case ARCMSR_MESSAGE_SAY_HELLO: {
2216ad6d6297SScott Long 			int8_t * hello_string = "Hello! I am ARCMSR";
2217ad6d6297SScott Long 
2218ad6d6297SScott Long 			memcpy(pcmdmessagefld->messagedatabuffer, hello_string
2219ad6d6297SScott Long 				, (int16_t)strlen(hello_string));
2220ad6d6297SScott Long 			pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
2221ad6d6297SScott Long 		}
2222ad6d6297SScott Long 		break;
2223ad6d6297SScott Long 	case ARCMSR_MESSAGE_SAY_GOODBYE:
2224ad6d6297SScott Long 		arcmsr_iop_parking(acb);
2225ad6d6297SScott Long 		break;
2226ad6d6297SScott Long 	case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE:
2227ad6d6297SScott Long 		arcmsr_flush_adapter_cache(acb);
2228ad6d6297SScott Long 		break;
2229ad6d6297SScott Long 	default:
2230ad6d6297SScott Long 		retvalue = ARCMSR_MESSAGE_FAIL;
2231ad6d6297SScott Long 	}
2232ad6d6297SScott Long message_out:
2233ad6d6297SScott Long 	return retvalue;
2234f1c579b1SScott Long }
2235f1c579b1SScott Long /*
2236f1c579b1SScott Long *********************************************************************
2237f1c579b1SScott Long *********************************************************************
2238f1c579b1SScott Long */
2239ad6d6297SScott Long static void arcmsr_executesrb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
2240f1c579b1SScott Long {
2241ad6d6297SScott Long 	struct CommandControlBlock *srb=(struct CommandControlBlock *)arg;
2242ad6d6297SScott Long 	struct AdapterControlBlock *acb=(struct AdapterControlBlock *)srb->acb;
2243f1c579b1SScott Long 	union ccb * pccb;
2244ad6d6297SScott Long 	int target, lun;
2245f1c579b1SScott Long 
2246ad6d6297SScott Long 	pccb=srb->pccb;
2247ad6d6297SScott Long 	target=pccb->ccb_h.target_id;
2248ad6d6297SScott Long 	lun=pccb->ccb_h.target_lun;
2249ad6d6297SScott Long 	if(error != 0) {
2250ad6d6297SScott Long 		if(error != EFBIG) {
225144f05562SScott Long 			printf("arcmsr%d: unexpected error %x"
225244f05562SScott Long 				" returned from 'bus_dmamap_load' \n"
2253ad6d6297SScott Long 				, acb->pci_unit, error);
2254f1c579b1SScott Long 		}
2255ad6d6297SScott Long 		if((pccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) {
225615735becSScott Long 			pccb->ccb_h.status |= CAM_REQ_TOO_BIG;
2257f1c579b1SScott Long 		}
2258ad6d6297SScott Long 		arcmsr_srb_complete(srb, 0);
2259f1c579b1SScott Long 		return;
2260f1c579b1SScott Long 	}
2261ad6d6297SScott Long 	if(nseg > ARCMSR_MAX_SG_ENTRIES) {
2262ad6d6297SScott Long 		pccb->ccb_h.status |= CAM_REQ_TOO_BIG;
2263ad6d6297SScott Long 		arcmsr_srb_complete(srb, 0);
2264ad6d6297SScott Long 		return;
2265f1c579b1SScott Long 	}
2266ad6d6297SScott Long 	if(acb->acb_flags & ACB_F_BUS_RESET) {
2267ad6d6297SScott Long 		printf("arcmsr%d: bus reset and return busy \n", acb->pci_unit);
2268ad6d6297SScott Long 		pccb->ccb_h.status |= CAM_SCSI_BUS_RESET;
2269ad6d6297SScott Long 		arcmsr_srb_complete(srb, 0);
2270ad6d6297SScott Long 		return;
2271ad6d6297SScott Long 	}
2272ad6d6297SScott Long 	if(acb->devstate[target][lun]==ARECA_RAID_GONE) {
2273ad6d6297SScott Long 		u_int8_t block_cmd;
2274ad6d6297SScott Long 
2275ad6d6297SScott Long 		block_cmd=pccb->csio.cdb_io.cdb_bytes[0] & 0x0f;
2276ad6d6297SScott Long 		if(block_cmd==0x08 || block_cmd==0x0a) {
2277ad6d6297SScott Long 			printf("arcmsr%d:block 'read/write' command "
2278ad6d6297SScott Long 				"with gone raid volume Cmd=%2x, TargetId=%d, Lun=%d \n"
2279ad6d6297SScott Long 				, acb->pci_unit, block_cmd, target, lun);
2280ad6d6297SScott Long 			pccb->ccb_h.status |= CAM_DEV_NOT_THERE;
2281ad6d6297SScott Long 			arcmsr_srb_complete(srb, 0);
2282ad6d6297SScott Long 			return;
2283ad6d6297SScott Long 		}
2284ad6d6297SScott Long 	}
2285ad6d6297SScott Long 	if((pccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_INPROG) {
2286ad6d6297SScott Long 		if(nseg != 0) {
2287ad6d6297SScott Long 			bus_dmamap_unload(acb->dm_segs_dmat, srb->dm_segs_dmamap);
2288ad6d6297SScott Long 		}
2289ad6d6297SScott Long 		arcmsr_srb_complete(srb, 0);
2290f1c579b1SScott Long 		return;
2291f1c579b1SScott Long 	}
2292ad6d6297SScott Long 	if(acb->srboutstandingcount >= ARCMSR_MAX_OUTSTANDING_CMD) {
229315735becSScott Long 		xpt_freeze_simq(acb->psim, 1);
229415735becSScott Long 		pccb->ccb_h.status = CAM_REQUEUE_REQ;
2295dc3a205bSScott Long 		acb->acb_flags |= ACB_F_CAM_DEV_QFRZN;
2296ad6d6297SScott Long 		arcmsr_srb_complete(srb, 0);
2297ad6d6297SScott Long 		return;
2298f1c579b1SScott Long 	}
229915735becSScott Long 	pccb->ccb_h.status |= CAM_SIM_QUEUED;
2300ad6d6297SScott Long 	arcmsr_build_srb(srb, dm_segs, nseg);
2301*d74001adSXin LI /*	if (pccb->ccb_h.timeout != CAM_TIME_INFINITY)
2302*d74001adSXin LI 		callout_reset(&srb->ccb_callout, (pccb->ccb_h.timeout * hz) / 1000, arcmsr_srb_timeout, srb);
2303*d74001adSXin LI */
2304ad6d6297SScott Long 	arcmsr_post_srb(acb, srb);
2305f1c579b1SScott Long 	return;
2306f1c579b1SScott Long }
2307f1c579b1SScott Long /*
2308f1c579b1SScott Long *****************************************************************************************
2309f1c579b1SScott Long *****************************************************************************************
2310f1c579b1SScott Long */
2311ad6d6297SScott Long static u_int8_t arcmsr_seek_cmd2abort(union ccb * abortccb)
2312f1c579b1SScott Long {
2313ad6d6297SScott Long 	struct CommandControlBlock *srb;
2314ad6d6297SScott Long 	struct AdapterControlBlock *acb=(struct AdapterControlBlock *) abortccb->ccb_h.arcmsr_ccbacb_ptr;
231544f05562SScott Long 	u_int32_t intmask_org;
2316ad6d6297SScott Long 	int i=0;
2317f1c579b1SScott Long 
2318ad6d6297SScott Long 	acb->num_aborts++;
2319f1c579b1SScott Long 	/*
2320ad6d6297SScott Long 	***************************************************************************
2321f1c579b1SScott Long 	** It is the upper layer do abort command this lock just prior to calling us.
2322f1c579b1SScott Long 	** First determine if we currently own this command.
2323f1c579b1SScott Long 	** Start by searching the device queue. If not found
2324f1c579b1SScott Long 	** at all, and the system wanted us to just abort the
2325f1c579b1SScott Long 	** command return success.
2326ad6d6297SScott Long 	***************************************************************************
2327f1c579b1SScott Long 	*/
2328ad6d6297SScott Long 	if(acb->srboutstandingcount!=0) {
2329ad6d6297SScott Long 		for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++) {
2330ad6d6297SScott Long 			srb=acb->psrb_pool[i];
2331ad6d6297SScott Long 			if(srb->startdone==ARCMSR_SRB_START) {
2332ad6d6297SScott Long 				if(srb->pccb==abortccb) {
2333ad6d6297SScott Long 					srb->startdone=ARCMSR_SRB_ABORTED;
2334ad6d6297SScott Long 					printf("arcmsr%d:scsi id=%d lun=%d abort srb '%p'"
2335ad6d6297SScott Long 						"outstanding command \n"
2336ad6d6297SScott Long 						, acb->pci_unit, abortccb->ccb_h.target_id
2337ad6d6297SScott Long 						, abortccb->ccb_h.target_lun, srb);
2338ad6d6297SScott Long 					goto abort_outstanding_cmd;
2339f1c579b1SScott Long 				}
2340f1c579b1SScott Long 			}
2341f1c579b1SScott Long 		}
2342f1c579b1SScott Long 	}
2343f1c579b1SScott Long 	return(FALSE);
2344ad6d6297SScott Long abort_outstanding_cmd:
2345ad6d6297SScott Long 	/* disable all outbound interrupt */
234644f05562SScott Long 	intmask_org=arcmsr_disable_allintr(acb);
2347ad6d6297SScott Long 	arcmsr_polling_srbdone(acb, srb);
234844f05562SScott Long 	/* enable outbound Post Queue, outbound doorbell Interrupt */
234944f05562SScott Long 	arcmsr_enable_allintr(acb, intmask_org);
2350ad6d6297SScott Long 	return (TRUE);
2351f1c579b1SScott Long }
2352f1c579b1SScott Long /*
2353f1c579b1SScott Long ****************************************************************************
2354f1c579b1SScott Long ****************************************************************************
2355f1c579b1SScott Long */
2356ad6d6297SScott Long static void arcmsr_bus_reset(struct AdapterControlBlock *acb)
2357f1c579b1SScott Long {
2358ad6d6297SScott Long 	int retry=0;
2359f1c579b1SScott Long 
2360ad6d6297SScott Long 	acb->num_resets++;
2361ad6d6297SScott Long 	acb->acb_flags |=ACB_F_BUS_RESET;
2362ad6d6297SScott Long 	while(acb->srboutstandingcount!=0 && retry < 400) {
236344f05562SScott Long 		arcmsr_interrupt(acb);
2364ad6d6297SScott Long 		UDELAY(25000);
2365ad6d6297SScott Long 		retry++;
2366ad6d6297SScott Long 	}
2367ad6d6297SScott Long 	arcmsr_iop_reset(acb);
2368ad6d6297SScott Long 	acb->acb_flags &= ~ACB_F_BUS_RESET;
2369f1c579b1SScott Long 	return;
2370f1c579b1SScott Long }
2371f1c579b1SScott Long /*
2372ad6d6297SScott Long **************************************************************************
2373ad6d6297SScott Long **************************************************************************
2374ad6d6297SScott Long */
2375ad6d6297SScott Long static void arcmsr_handle_virtual_command(struct AdapterControlBlock *acb,
2376ad6d6297SScott Long 		union ccb * pccb)
2377ad6d6297SScott Long {
2378ad6d6297SScott Long 	pccb->ccb_h.status |= CAM_REQ_CMP;
2379ad6d6297SScott Long 	switch (pccb->csio.cdb_io.cdb_bytes[0]) {
2380ad6d6297SScott Long 	case INQUIRY: {
2381ad6d6297SScott Long 		unsigned char inqdata[36];
2382c2ede4b3SMartin Blapp 		char *buffer=pccb->csio.data_ptr;
2383ad6d6297SScott Long 
2384ad6d6297SScott Long 		if (pccb->ccb_h.target_lun) {
2385ad6d6297SScott Long 			pccb->ccb_h.status |= CAM_SEL_TIMEOUT;
2386ad6d6297SScott Long 			xpt_done(pccb);
2387ad6d6297SScott Long 			return;
2388ad6d6297SScott Long 		}
2389ad6d6297SScott Long 		inqdata[0] = T_PROCESSOR;
2390ad6d6297SScott Long 		/* Periph Qualifier & Periph Dev Type */
2391ad6d6297SScott Long 		inqdata[1] = 0;
2392ad6d6297SScott Long 		/* rem media bit & Dev Type Modifier */
2393ad6d6297SScott Long 		inqdata[2] = 0;
2394ad6d6297SScott Long 		/* ISO, ECMA, & ANSI versions */
2395ad6d6297SScott Long 		inqdata[4] = 31;
2396ad6d6297SScott Long 		/* length of additional data */
2397ad6d6297SScott Long 		strncpy(&inqdata[8], "Areca   ", 8);
2398ad6d6297SScott Long 		/* Vendor Identification */
2399ad6d6297SScott Long 		strncpy(&inqdata[16], "RAID controller ", 16);
2400ad6d6297SScott Long 		/* Product Identification */
2401ad6d6297SScott Long 		strncpy(&inqdata[32], "R001", 4); /* Product Revision */
2402ad6d6297SScott Long 		memcpy(buffer, inqdata, sizeof(inqdata));
2403ad6d6297SScott Long 		xpt_done(pccb);
2404ad6d6297SScott Long 	}
2405ad6d6297SScott Long 	break;
2406ad6d6297SScott Long 	case WRITE_BUFFER:
2407ad6d6297SScott Long 	case READ_BUFFER: {
2408ad6d6297SScott Long 		if (arcmsr_iop_message_xfer(acb, pccb)) {
2409ad6d6297SScott Long 			pccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
2410ad6d6297SScott Long 			pccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
2411ad6d6297SScott Long 		}
2412ad6d6297SScott Long 		xpt_done(pccb);
2413ad6d6297SScott Long 	}
2414ad6d6297SScott Long 	break;
2415ad6d6297SScott Long 	default:
2416ad6d6297SScott Long 		xpt_done(pccb);
2417ad6d6297SScott Long 	}
2418ad6d6297SScott Long }
2419ad6d6297SScott Long /*
2420f1c579b1SScott Long *********************************************************************
2421f1c579b1SScott Long *********************************************************************
2422f1c579b1SScott Long */
2423ad6d6297SScott Long static void arcmsr_action(struct cam_sim * psim, union ccb * pccb)
2424f1c579b1SScott Long {
2425ad6d6297SScott Long 	struct AdapterControlBlock *  acb;
2426f1c579b1SScott Long 
2427ad6d6297SScott Long 	acb=(struct AdapterControlBlock *) cam_sim_softc(psim);
2428ad6d6297SScott Long 	if(acb==NULL) {
2429ad6d6297SScott Long 		pccb->ccb_h.status |= CAM_REQ_INVALID;
2430f1c579b1SScott Long 		xpt_done(pccb);
2431f1c579b1SScott Long 		return;
2432f1c579b1SScott Long 	}
2433ad6d6297SScott Long 	switch (pccb->ccb_h.func_code) {
2434ad6d6297SScott Long 	case XPT_SCSI_IO: {
2435ad6d6297SScott Long 			struct CommandControlBlock *srb;
2436ad6d6297SScott Long 			int target=pccb->ccb_h.target_id;
2437f1c579b1SScott Long 
2438ad6d6297SScott Long 			if(target == 16) {
2439ad6d6297SScott Long 				/* virtual device for iop message transfer */
2440ad6d6297SScott Long 				arcmsr_handle_virtual_command(acb, pccb);
2441ad6d6297SScott Long 				return;
2442ad6d6297SScott Long 			}
2443ad6d6297SScott Long 			if((srb=arcmsr_get_freesrb(acb)) == NULL) {
2444ad6d6297SScott Long 				pccb->ccb_h.status |= CAM_RESRC_UNAVAIL;
2445f1c579b1SScott Long 				xpt_done(pccb);
2446f1c579b1SScott Long 				return;
2447f1c579b1SScott Long 			}
2448ad6d6297SScott Long 			pccb->ccb_h.arcmsr_ccbsrb_ptr=srb;
2449ad6d6297SScott Long 			pccb->ccb_h.arcmsr_ccbacb_ptr=acb;
2450ad6d6297SScott Long 			srb->pccb=pccb;
2451ad6d6297SScott Long 			if((pccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
2452ad6d6297SScott Long 				if(!(pccb->ccb_h.flags & CAM_SCATTER_VALID)) {
2453ad6d6297SScott Long 					/* Single buffer */
2454ad6d6297SScott Long 					if(!(pccb->ccb_h.flags & CAM_DATA_PHYS)) {
2455ad6d6297SScott Long 						/* Buffer is virtual */
2456ad6d6297SScott Long 						u_int32_t error, s;
2457f1c579b1SScott Long 
2458f1c579b1SScott Long 						s=splsoftvm();
2459ad6d6297SScott Long 						error =	bus_dmamap_load(acb->dm_segs_dmat
2460ad6d6297SScott Long 							, srb->dm_segs_dmamap
2461ad6d6297SScott Long 							, pccb->csio.data_ptr
2462ad6d6297SScott Long 							, pccb->csio.dxfer_len
2463ad6d6297SScott Long 							, arcmsr_executesrb, srb, /*flags*/0);
2464ad6d6297SScott Long 	         				if(error == EINPROGRESS) {
2465ad6d6297SScott Long 							xpt_freeze_simq(acb->psim, 1);
2466f1c579b1SScott Long 							pccb->ccb_h.status |= CAM_RELEASE_SIMQ;
2467f1c579b1SScott Long 						}
2468f1c579b1SScott Long 						splx(s);
2469ad6d6297SScott Long 					} else {
2470ad6d6297SScott Long 						/* Buffer is physical */
24711c7e9358SScott Long 						panic("arcmsr: CAM_DATA_PHYS not supported");
2472f1c579b1SScott Long 					}
2473ad6d6297SScott Long 				} else {
2474ad6d6297SScott Long 					/* Scatter/gather list */
2475f1c579b1SScott Long 					struct bus_dma_segment *segs;
2476f1c579b1SScott Long 
2477ad6d6297SScott Long 					if((pccb->ccb_h.flags & CAM_SG_LIST_PHYS) == 0
2478ad6d6297SScott Long 					|| (pccb->ccb_h.flags & CAM_DATA_PHYS) != 0) {
2479ad6d6297SScott Long 						pccb->ccb_h.status |= CAM_PROVIDE_FAIL;
2480f1c579b1SScott Long 						xpt_done(pccb);
2481ad6d6297SScott Long 						free(srb, M_DEVBUF);
2482f1c579b1SScott Long 						return;
2483f1c579b1SScott Long 					}
2484f1c579b1SScott Long 					segs=(struct bus_dma_segment *)pccb->csio.data_ptr;
2485ad6d6297SScott Long 					arcmsr_executesrb(srb, segs, pccb->csio.sglist_cnt, 0);
2486f1c579b1SScott Long 				}
2487ad6d6297SScott Long 			} else {
2488ad6d6297SScott Long 				arcmsr_executesrb(srb, NULL, 0, 0);
2489f1c579b1SScott Long 			}
2490f1c579b1SScott Long 			break;
2491f1c579b1SScott Long 		}
2492ad6d6297SScott Long 	case XPT_TARGET_IO: {
2493ad6d6297SScott Long 			/* target mode not yet support vendor specific commands. */
2494ad6d6297SScott Long 			pccb->ccb_h.status |= CAM_REQ_CMP;
2495f1c579b1SScott Long 			xpt_done(pccb);
2496f1c579b1SScott Long 			break;
2497f1c579b1SScott Long 		}
2498ad6d6297SScott Long 	case XPT_PATH_INQ: {
2499f1c579b1SScott Long 			struct ccb_pathinq *cpi= &pccb->cpi;
2500f1c579b1SScott Long 
2501f1c579b1SScott Long 			cpi->version_num=1;
2502f1c579b1SScott Long 			cpi->hba_inquiry=PI_SDTR_ABLE | PI_TAG_ABLE;
2503f1c579b1SScott Long 			cpi->target_sprt=0;
2504f1c579b1SScott Long 			cpi->hba_misc=0;
2505f1c579b1SScott Long 			cpi->hba_eng_cnt=0;
2506ad6d6297SScott Long 			cpi->max_target=ARCMSR_MAX_TARGETID;        /* 0-16 */
2507ad6d6297SScott Long 			cpi->max_lun=ARCMSR_MAX_TARGETLUN;	    /* 0-7 */
2508ad6d6297SScott Long 			cpi->initiator_id=ARCMSR_SCSI_INITIATOR_ID; /* 255 */
2509f1c579b1SScott Long 			cpi->bus_id=cam_sim_bus(psim);
2510f1c579b1SScott Long 			strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
2511f1c579b1SScott Long 			strncpy(cpi->hba_vid, "ARCMSR", HBA_IDLEN);
2512f1c579b1SScott Long 			strncpy(cpi->dev_name, cam_sim_name(psim), DEV_IDLEN);
2513f1c579b1SScott Long 			cpi->unit_number=cam_sim_unit(psim);
251444f05562SScott Long 		#ifdef	CAM_NEW_TRAN_CODE
2515fa9ed865SMatt Jacob 			cpi->transport = XPORT_SPI;
2516fa9ed865SMatt Jacob 			cpi->transport_version = 2;
2517fa9ed865SMatt Jacob 			cpi->protocol = PROTO_SCSI;
2518fa9ed865SMatt Jacob 			cpi->protocol_version = SCSI_REV_2;
251944f05562SScott Long 		#endif
2520ad6d6297SScott Long 			cpi->ccb_h.status |= CAM_REQ_CMP;
2521f1c579b1SScott Long 			xpt_done(pccb);
2522f1c579b1SScott Long 			break;
2523f1c579b1SScott Long 		}
2524ad6d6297SScott Long 	case XPT_ABORT: {
2525f1c579b1SScott Long 			union ccb *pabort_ccb;
2526f1c579b1SScott Long 
2527f1c579b1SScott Long 			pabort_ccb=pccb->cab.abort_ccb;
2528ad6d6297SScott Long 			switch (pabort_ccb->ccb_h.func_code) {
2529f1c579b1SScott Long 			case XPT_ACCEPT_TARGET_IO:
2530f1c579b1SScott Long 			case XPT_IMMED_NOTIFY:
2531f1c579b1SScott Long 			case XPT_CONT_TARGET_IO:
2532ad6d6297SScott Long 				if(arcmsr_seek_cmd2abort(pabort_ccb)==TRUE) {
2533ad6d6297SScott Long 					pabort_ccb->ccb_h.status |= CAM_REQ_ABORTED;
2534f1c579b1SScott Long 					xpt_done(pabort_ccb);
2535ad6d6297SScott Long 					pccb->ccb_h.status |= CAM_REQ_CMP;
2536ad6d6297SScott Long 				} else {
2537f1c579b1SScott Long 					xpt_print_path(pabort_ccb->ccb_h.path);
2538f1c579b1SScott Long 					printf("Not found\n");
2539ad6d6297SScott Long 					pccb->ccb_h.status |= CAM_PATH_INVALID;
2540f1c579b1SScott Long 				}
2541f1c579b1SScott Long 				break;
2542f1c579b1SScott Long 			case XPT_SCSI_IO:
2543ad6d6297SScott Long 				pccb->ccb_h.status |= CAM_UA_ABORT;
2544f1c579b1SScott Long 				break;
2545f1c579b1SScott Long 			default:
2546ad6d6297SScott Long 				pccb->ccb_h.status |= CAM_REQ_INVALID;
2547f1c579b1SScott Long 				break;
2548f1c579b1SScott Long 			}
2549f1c579b1SScott Long 			xpt_done(pccb);
2550f1c579b1SScott Long 			break;
2551f1c579b1SScott Long 		}
2552f1c579b1SScott Long 	case XPT_RESET_BUS:
2553ad6d6297SScott Long 	case XPT_RESET_DEV: {
2554ad6d6297SScott Long 			u_int32_t     i;
2555f1c579b1SScott Long 
2556ad6d6297SScott Long 			arcmsr_bus_reset(acb);
2557ad6d6297SScott Long 			for (i=0; i < 500; i++) {
2558f1c579b1SScott Long 				DELAY(1000);
2559f1c579b1SScott Long 			}
2560ad6d6297SScott Long 			pccb->ccb_h.status |= CAM_REQ_CMP;
2561f1c579b1SScott Long 			xpt_done(pccb);
2562f1c579b1SScott Long 			break;
2563f1c579b1SScott Long 		}
2564ad6d6297SScott Long 	case XPT_TERM_IO: {
2565ad6d6297SScott Long 			pccb->ccb_h.status |= CAM_REQ_INVALID;
2566f1c579b1SScott Long 			xpt_done(pccb);
2567f1c579b1SScott Long 			break;
2568f1c579b1SScott Long 		}
2569ad6d6297SScott Long 	case XPT_GET_TRAN_SETTINGS: {
2570ad6d6297SScott Long 			struct ccb_trans_settings *cts;
2571ad6d6297SScott Long 
2572ad6d6297SScott Long 			if(pccb->ccb_h.target_id == 16) {
2573ad6d6297SScott Long 				pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL;
2574ad6d6297SScott Long 				xpt_done(pccb);
2575ad6d6297SScott Long 				break;
2576ad6d6297SScott Long 			}
2577ad6d6297SScott Long 			cts= &pccb->cts;
257844f05562SScott Long 		#ifdef	CAM_NEW_TRAN_CODE
257944f05562SScott Long 			{
258044f05562SScott Long 				struct ccb_trans_settings_scsi *scsi;
258144f05562SScott Long 				struct ccb_trans_settings_spi *spi;
258244f05562SScott Long 
2583ad6d6297SScott Long 				scsi = &cts->proto_specific.scsi;
2584ad6d6297SScott Long 				spi = &cts->xport_specific.spi;
2585fa9ed865SMatt Jacob 				cts->protocol = PROTO_SCSI;
2586fa9ed865SMatt Jacob 				cts->protocol_version = SCSI_REV_2;
2587fa9ed865SMatt Jacob 				cts->transport = XPORT_SPI;
2588fa9ed865SMatt Jacob 				cts->transport_version = 2;
2589fa9ed865SMatt Jacob 				spi->flags = CTS_SPI_FLAGS_DISC_ENB;
2590fa9ed865SMatt Jacob 				spi->sync_period=3;
2591fa9ed865SMatt Jacob 				spi->sync_offset=32;
2592fa9ed865SMatt Jacob 				spi->bus_width=MSG_EXT_WDTR_BUS_16_BIT;
2593fa9ed865SMatt Jacob 				scsi->flags = CTS_SCSI_FLAGS_TAG_ENB;
25949d98ff4dSScott Long 				spi->valid = CTS_SPI_VALID_DISC
25959d98ff4dSScott Long 					| CTS_SPI_VALID_SYNC_RATE
2596fa9ed865SMatt Jacob 					| CTS_SPI_VALID_SYNC_OFFSET
2597fa9ed865SMatt Jacob 					| CTS_SPI_VALID_BUS_WIDTH;
2598fa9ed865SMatt Jacob 				scsi->valid = CTS_SCSI_VALID_TQ;
259944f05562SScott Long 			}
260044f05562SScott Long 		#else
260144f05562SScott Long 			{
260244f05562SScott Long 				cts->flags=(CCB_TRANS_DISC_ENB | CCB_TRANS_TAG_ENB);
260344f05562SScott Long 				cts->sync_period=3;
260444f05562SScott Long 				cts->sync_offset=32;
260544f05562SScott Long 				cts->bus_width=MSG_EXT_WDTR_BUS_16_BIT;
260644f05562SScott Long 				cts->valid=CCB_TRANS_SYNC_RATE_VALID |
260744f05562SScott Long 				CCB_TRANS_SYNC_OFFSET_VALID |
260844f05562SScott Long 				CCB_TRANS_BUS_WIDTH_VALID |
260944f05562SScott Long 				CCB_TRANS_DISC_VALID |
261044f05562SScott Long 				CCB_TRANS_TQ_VALID;
261144f05562SScott Long 			}
261244f05562SScott Long 		#endif
2613ad6d6297SScott Long 			pccb->ccb_h.status |= CAM_REQ_CMP;
2614ad6d6297SScott Long 			xpt_done(pccb);
2615ad6d6297SScott Long 			break;
2616ad6d6297SScott Long 		}
2617ad6d6297SScott Long 	case XPT_SET_TRAN_SETTINGS: {
2618ad6d6297SScott Long 			pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL;
2619ad6d6297SScott Long 			xpt_done(pccb);
2620ad6d6297SScott Long 			break;
2621ad6d6297SScott Long 		}
2622ad6d6297SScott Long 	case XPT_CALC_GEOMETRY: {
2623ad6d6297SScott Long 			struct ccb_calc_geometry *ccg;
2624ad6d6297SScott Long 			u_int32_t size_mb;
2625ad6d6297SScott Long 			u_int32_t secs_per_cylinder;
2626ad6d6297SScott Long 
2627ad6d6297SScott Long 			if(pccb->ccb_h.target_id == 16) {
2628ad6d6297SScott Long 				pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL;
2629ad6d6297SScott Long 				xpt_done(pccb);
2630ad6d6297SScott Long 				break;
2631ad6d6297SScott Long 			}
2632f1c579b1SScott Long 			ccg= &pccb->ccg;
2633ad6d6297SScott Long 			if (ccg->block_size == 0) {
2634ad6d6297SScott Long 				pccb->ccb_h.status = CAM_REQ_INVALID;
2635ad6d6297SScott Long 				xpt_done(pccb);
2636ad6d6297SScott Long 				break;
2637ad6d6297SScott Long 			}
2638ad6d6297SScott Long 			if(((1024L * 1024L)/ccg->block_size) < 0) {
2639ad6d6297SScott Long 				pccb->ccb_h.status = CAM_REQ_INVALID;
2640ad6d6297SScott Long 				xpt_done(pccb);
2641ad6d6297SScott Long 				break;
2642ad6d6297SScott Long 			}
2643f1c579b1SScott Long 			size_mb=ccg->volume_size/((1024L * 1024L)/ccg->block_size);
2644ad6d6297SScott Long 			if(size_mb > 1024 ) {
2645f1c579b1SScott Long 				ccg->heads=255;
2646f1c579b1SScott Long 				ccg->secs_per_track=63;
2647ad6d6297SScott Long 			} else {
2648f1c579b1SScott Long 				ccg->heads=64;
2649f1c579b1SScott Long 				ccg->secs_per_track=32;
2650f1c579b1SScott Long 			}
2651f1c579b1SScott Long 			secs_per_cylinder=ccg->heads * ccg->secs_per_track;
2652f1c579b1SScott Long 			ccg->cylinders=ccg->volume_size / secs_per_cylinder;
2653ad6d6297SScott Long 			pccb->ccb_h.status |= CAM_REQ_CMP;
2654f1c579b1SScott Long 			xpt_done(pccb);
2655f1c579b1SScott Long 			break;
2656f1c579b1SScott Long 		}
2657f1c579b1SScott Long 	default:
2658ad6d6297SScott Long 		pccb->ccb_h.status |= CAM_REQ_INVALID;
2659f1c579b1SScott Long 		xpt_done(pccb);
2660f1c579b1SScott Long 		break;
2661f1c579b1SScott Long 	}
2662f1c579b1SScott Long 	return;
2663f1c579b1SScott Long }
2664f1c579b1SScott Long /*
2665f1c579b1SScott Long **********************************************************************
2666f1c579b1SScott Long **********************************************************************
2667f1c579b1SScott Long */
266844f05562SScott Long static void arcmsr_start_hba_bgrb(struct AdapterControlBlock *acb)
2669f1c579b1SScott Long {
2670ad6d6297SScott Long 	acb->acb_flags |= ACB_F_MSG_START_BGRB;
267144f05562SScott Long 	CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB);
267244f05562SScott Long 	if(!arcmsr_hba_wait_msgint_ready(acb)) {
2673ad6d6297SScott Long 		printf("arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit);
2674ad6d6297SScott Long 	}
2675f1c579b1SScott Long 	return;
2676f1c579b1SScott Long }
2677f1c579b1SScott Long /*
2678f1c579b1SScott Long **********************************************************************
2679f1c579b1SScott Long **********************************************************************
2680f1c579b1SScott Long */
268144f05562SScott Long static void arcmsr_start_hbb_bgrb(struct AdapterControlBlock *acb)
268244f05562SScott Long {
268344f05562SScott Long 	acb->acb_flags |= ACB_F_MSG_START_BGRB;
2684*d74001adSXin LI 	CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell,  ARCMSR_MESSAGE_START_BGRB);
268544f05562SScott Long 	if(!arcmsr_hbb_wait_msgint_ready(acb)) {
268644f05562SScott Long 		printf( "arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit);
268744f05562SScott Long 	}
268844f05562SScott Long 	return;
268944f05562SScott Long }
269044f05562SScott Long /*
269144f05562SScott Long **********************************************************************
269244f05562SScott Long **********************************************************************
269344f05562SScott Long */
2694*d74001adSXin LI static void arcmsr_start_hbc_bgrb(struct AdapterControlBlock *acb)
2695*d74001adSXin LI {
2696*d74001adSXin LI 	acb->acb_flags |= ACB_F_MSG_START_BGRB;
2697*d74001adSXin LI 	CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB);
2698*d74001adSXin LI 	CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE);
2699*d74001adSXin LI 	if(!arcmsr_hbc_wait_msgint_ready(acb)) {
2700*d74001adSXin LI 		printf("arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit);
2701*d74001adSXin LI 	}
2702*d74001adSXin LI 	return;
2703*d74001adSXin LI }
2704*d74001adSXin LI /*
2705*d74001adSXin LI **********************************************************************
2706*d74001adSXin LI **********************************************************************
2707*d74001adSXin LI */
270844f05562SScott Long static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb)
270944f05562SScott Long {
271044f05562SScott Long 	switch (acb->adapter_type) {
271144f05562SScott Long 	case ACB_ADAPTER_TYPE_A:
271244f05562SScott Long 		arcmsr_start_hba_bgrb(acb);
271344f05562SScott Long 		break;
271444f05562SScott Long 	case ACB_ADAPTER_TYPE_B:
271544f05562SScott Long 		arcmsr_start_hbb_bgrb(acb);
271644f05562SScott Long 		break;
2717*d74001adSXin LI 	case ACB_ADAPTER_TYPE_C:
2718*d74001adSXin LI 		arcmsr_start_hbc_bgrb(acb);
2719*d74001adSXin LI 		break;
272044f05562SScott Long 	}
272144f05562SScott Long 	return;
272244f05562SScott Long }
272344f05562SScott Long /*
272444f05562SScott Long **********************************************************************
272544f05562SScott Long **
272644f05562SScott Long **********************************************************************
272744f05562SScott Long */
272844f05562SScott Long static void arcmsr_polling_hba_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb)
2729f1c579b1SScott Long {
2730ad6d6297SScott Long 	struct CommandControlBlock *srb;
273144f05562SScott Long 	u_int32_t flag_srb, outbound_intstatus, poll_srb_done=0, poll_count=0;
2732*d74001adSXin LI 	u_int16_t	error;
2733f1c579b1SScott Long 
273444f05562SScott Long polling_ccb_retry:
2735ad6d6297SScott Long 	poll_count++;
2736*d74001adSXin LI 	outbound_intstatus=CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & acb->outbound_int_enable;
2737*d74001adSXin LI 	CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, outbound_intstatus);	/*clear interrupt*/
273844f05562SScott Long 	bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
2739ad6d6297SScott Long 	while(1) {
274044f05562SScott Long 		if((flag_srb=CHIP_REG_READ32(HBA_MessageUnit,
274144f05562SScott Long 			0, outbound_queueport))==0xFFFFFFFF) {
2742ad6d6297SScott Long 			if(poll_srb_done) {
2743ad6d6297SScott Long 				break;/*chip FIFO no ccb for completion already*/
2744ad6d6297SScott Long 			} else {
2745ad6d6297SScott Long 				UDELAY(25000);
2746*d74001adSXin LI 				if ((poll_count > 100) && (poll_srb != NULL)) {
2747ad6d6297SScott Long 					break;
2748f1c579b1SScott Long 				}
274944f05562SScott Long 				goto polling_ccb_retry;
2750f1c579b1SScott Long 			}
2751ad6d6297SScott Long 		}
2752ad6d6297SScott Long 		/* check if command done with no error*/
275344f05562SScott Long 		srb=(struct CommandControlBlock *)
275444f05562SScott Long 			(acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/
2755*d74001adSXin LI         error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE;
275644f05562SScott Long 		poll_srb_done = (srb==poll_srb) ? 1:0;
2757ad6d6297SScott Long 		if((srb->acb!=acb) || (srb->startdone!=ARCMSR_SRB_START)) {
275844f05562SScott Long 			if(srb->startdone==ARCMSR_SRB_ABORTED) {
2759ad6d6297SScott Long 				printf("arcmsr%d: scsi id=%d lun=%d srb='%p'"
2760ad6d6297SScott Long 					"poll command abort successfully \n"
2761ad6d6297SScott Long 					, acb->pci_unit
2762ad6d6297SScott Long 					, srb->pccb->ccb_h.target_id
2763ad6d6297SScott Long 					, srb->pccb->ccb_h.target_lun, srb);
2764ad6d6297SScott Long 				srb->pccb->ccb_h.status |= CAM_REQ_ABORTED;
2765ad6d6297SScott Long 				arcmsr_srb_complete(srb, 1);
2766ad6d6297SScott Long 				continue;
2767ad6d6297SScott Long 			}
2768ad6d6297SScott Long 			printf("arcmsr%d: polling get an illegal srb command done srb='%p'"
2769ad6d6297SScott Long 				"srboutstandingcount=%d \n"
2770ad6d6297SScott Long 				, acb->pci_unit
2771ad6d6297SScott Long 				, srb, acb->srboutstandingcount);
2772ad6d6297SScott Long 			continue;
2773ad6d6297SScott Long 		}
2774*d74001adSXin LI 		arcmsr_report_srb_state(acb, srb, error);
2775ad6d6297SScott Long 	}	/*drain reply FIFO*/
2776f1c579b1SScott Long 	return;
2777f1c579b1SScott Long }
2778f1c579b1SScott Long /*
2779f1c579b1SScott Long **********************************************************************
278044f05562SScott Long **
2781ad6d6297SScott Long **********************************************************************
2782ad6d6297SScott Long */
278344f05562SScott Long static void arcmsr_polling_hbb_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb)
278444f05562SScott Long {
278544f05562SScott Long 	struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu;
278644f05562SScott Long 	struct CommandControlBlock *srb;
278744f05562SScott Long 	u_int32_t flag_srb, poll_srb_done=0, poll_count=0;
278844f05562SScott Long 	int index;
2789*d74001adSXin LI 	u_int16_t	error;
279044f05562SScott Long 
279144f05562SScott Long polling_ccb_retry:
279244f05562SScott Long 	poll_count++;
279344f05562SScott Long 	CHIP_REG_WRITE32(HBB_DOORBELL,
279444f05562SScott Long 	0, iop2drv_doorbell, ARCMSR_DOORBELL_INT_CLEAR_PATTERN); /* clear doorbell interrupt */
279544f05562SScott Long 	bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
279644f05562SScott Long 	while(1) {
279744f05562SScott Long 		index=phbbmu->doneq_index;
279844f05562SScott Long 		if((flag_srb=phbbmu->done_qbuffer[index]) == 0) {
279944f05562SScott Long 			if(poll_srb_done) {
280044f05562SScott Long 				break;/*chip FIFO no ccb for completion already*/
280144f05562SScott Long 			} else {
280244f05562SScott Long 				UDELAY(25000);
2803*d74001adSXin LI 			    if ((poll_count > 100) && (poll_srb != NULL)) {
280444f05562SScott Long 					break;
280544f05562SScott Long 				}
280644f05562SScott Long 				goto polling_ccb_retry;
280744f05562SScott Long 			}
280844f05562SScott Long 		}
280944f05562SScott Long 		phbbmu->done_qbuffer[index]=0;
281044f05562SScott Long 		index++;
281144f05562SScott Long 		index %= ARCMSR_MAX_HBB_POSTQUEUE;     /*if last index number set it to 0 */
281244f05562SScott Long 		phbbmu->doneq_index=index;
281344f05562SScott Long 		/* check if command done with no error*/
281444f05562SScott Long 		srb=(struct CommandControlBlock *)
281544f05562SScott Long 			(acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/
2816*d74001adSXin LI         error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE;
281744f05562SScott Long 		poll_srb_done = (srb==poll_srb) ? 1:0;
281844f05562SScott Long 		if((srb->acb!=acb) || (srb->startdone!=ARCMSR_SRB_START)) {
281944f05562SScott Long 			if(srb->startdone==ARCMSR_SRB_ABORTED) {
282044f05562SScott Long 				printf("arcmsr%d: scsi id=%d lun=%d srb='%p'"
282144f05562SScott Long 					"poll command abort successfully \n"
282244f05562SScott Long 					, acb->pci_unit
282344f05562SScott Long 					, srb->pccb->ccb_h.target_id
282444f05562SScott Long 					, srb->pccb->ccb_h.target_lun, srb);
282544f05562SScott Long 				srb->pccb->ccb_h.status |= CAM_REQ_ABORTED;
282644f05562SScott Long 				arcmsr_srb_complete(srb, 1);
282744f05562SScott Long 				continue;
282844f05562SScott Long 			}
282944f05562SScott Long 			printf("arcmsr%d: polling get an illegal srb command done srb='%p'"
283044f05562SScott Long 				"srboutstandingcount=%d \n"
283144f05562SScott Long 				, acb->pci_unit
283244f05562SScott Long 				, srb, acb->srboutstandingcount);
283344f05562SScott Long 			continue;
283444f05562SScott Long 		}
2835*d74001adSXin LI 		arcmsr_report_srb_state(acb, srb, error);
2836*d74001adSXin LI 	}	/*drain reply FIFO*/
2837*d74001adSXin LI 	return;
2838*d74001adSXin LI }
2839*d74001adSXin LI /*
2840*d74001adSXin LI **********************************************************************
2841*d74001adSXin LI **
2842*d74001adSXin LI **********************************************************************
2843*d74001adSXin LI */
2844*d74001adSXin LI static void arcmsr_polling_hbc_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb)
2845*d74001adSXin LI {
2846*d74001adSXin LI 	struct CommandControlBlock *srb;
2847*d74001adSXin LI 	u_int32_t flag_srb, poll_srb_done=0, poll_count=0;
2848*d74001adSXin LI 	u_int16_t	error;
2849*d74001adSXin LI 
2850*d74001adSXin LI polling_ccb_retry:
2851*d74001adSXin LI 	poll_count++;
2852*d74001adSXin LI 	bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
2853*d74001adSXin LI 	while(1) {
2854*d74001adSXin LI 		if(!(CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR)) {
2855*d74001adSXin LI 			if(poll_srb_done) {
2856*d74001adSXin LI 				break;/*chip FIFO no ccb for completion already*/
2857*d74001adSXin LI 			} else {
2858*d74001adSXin LI 				UDELAY(25000);
2859*d74001adSXin LI 			    if ((poll_count > 100) && (poll_srb != NULL)) {
2860*d74001adSXin LI 					break;
2861*d74001adSXin LI 				}
2862*d74001adSXin LI 			    if (acb->srboutstandingcount == 0) {
2863*d74001adSXin LI 				    break;
2864*d74001adSXin LI 			    }
2865*d74001adSXin LI 				goto polling_ccb_retry;
2866*d74001adSXin LI 			}
2867*d74001adSXin LI 		}
2868*d74001adSXin LI 		flag_srb = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_queueport_low);
2869*d74001adSXin LI 		/* check if command done with no error*/
2870*d74001adSXin LI 		srb=(struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb & 0xFFFFFFF0));/*frame must be 32 bytes aligned*/
2871*d74001adSXin LI         error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1)?TRUE:FALSE;
2872*d74001adSXin LI 		if (poll_srb != NULL)
2873*d74001adSXin LI 			poll_srb_done = (srb==poll_srb) ? 1:0;
2874*d74001adSXin LI 		if((srb->acb!=acb) || (srb->startdone!=ARCMSR_SRB_START)) {
2875*d74001adSXin LI 			if(srb->startdone==ARCMSR_SRB_ABORTED) {
2876*d74001adSXin LI 				printf("arcmsr%d: scsi id=%d lun=%d srb='%p'poll command abort successfully \n"
2877*d74001adSXin LI 						, acb->pci_unit, srb->pccb->ccb_h.target_id, srb->pccb->ccb_h.target_lun, srb);
2878*d74001adSXin LI 				srb->pccb->ccb_h.status |= CAM_REQ_ABORTED;
2879*d74001adSXin LI 				arcmsr_srb_complete(srb, 1);
2880*d74001adSXin LI 				continue;
2881*d74001adSXin LI 			}
2882*d74001adSXin LI 			printf("arcmsr%d: polling get an illegal srb command done srb='%p'srboutstandingcount=%d \n"
2883*d74001adSXin LI 					, acb->pci_unit, srb, acb->srboutstandingcount);
2884*d74001adSXin LI 			continue;
2885*d74001adSXin LI 		}
2886*d74001adSXin LI 		arcmsr_report_srb_state(acb, srb, error);
288744f05562SScott Long 	}	/*drain reply FIFO*/
288844f05562SScott Long 	return;
288944f05562SScott Long }
289044f05562SScott Long /*
289144f05562SScott Long **********************************************************************
289244f05562SScott Long **********************************************************************
289344f05562SScott Long */
289444f05562SScott Long static void arcmsr_polling_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb)
289544f05562SScott Long {
289644f05562SScott Long 	switch (acb->adapter_type) {
289744f05562SScott Long 	case ACB_ADAPTER_TYPE_A: {
289844f05562SScott Long 			arcmsr_polling_hba_srbdone(acb, poll_srb);
289944f05562SScott Long 		}
290044f05562SScott Long 		break;
290144f05562SScott Long 	case ACB_ADAPTER_TYPE_B: {
290244f05562SScott Long 			arcmsr_polling_hbb_srbdone(acb, poll_srb);
290344f05562SScott Long 		}
290444f05562SScott Long 		break;
2905*d74001adSXin LI 	case ACB_ADAPTER_TYPE_C: {
2906*d74001adSXin LI 			arcmsr_polling_hbc_srbdone(acb, poll_srb);
2907*d74001adSXin LI 		}
2908*d74001adSXin LI 		break;
290944f05562SScott Long 	}
291044f05562SScott Long }
291144f05562SScott Long /*
291244f05562SScott Long **********************************************************************
291344f05562SScott Long **********************************************************************
291444f05562SScott Long */
291544f05562SScott Long static void arcmsr_get_hba_config(struct AdapterControlBlock *acb)
2916ad6d6297SScott Long {
2917ad6d6297SScott Long 	char *acb_firm_model=acb->firm_model;
2918ad6d6297SScott Long 	char *acb_firm_version=acb->firm_version;
2919*d74001adSXin LI 	char *acb_device_map = acb->device_map;
2920*d74001adSXin LI 	size_t iop_firm_model=offsetof(struct HBA_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]);	/*firm_model,15,60-67*/
2921*d74001adSXin LI 	size_t iop_firm_version=offsetof(struct HBA_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]);	/*firm_version,17,68-83*/
2922*d74001adSXin LI 	size_t iop_device_map = offsetof(struct HBA_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
2923ad6d6297SScott Long 	int i;
2924ad6d6297SScott Long 
292544f05562SScott Long 	CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG);
292644f05562SScott Long 	if(!arcmsr_hba_wait_msgint_ready(acb)) {
2927*d74001adSXin LI 		printf("arcmsr%d: wait 'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit);
2928ad6d6297SScott Long 	}
2929ad6d6297SScott Long 	i=0;
2930ad6d6297SScott Long 	while(i<8) {
293144f05562SScott Long 		*acb_firm_model=bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_model+i);
2932ad6d6297SScott Long 		/* 8 bytes firm_model, 15, 60-67*/
2933ad6d6297SScott Long 		acb_firm_model++;
2934ad6d6297SScott Long 		i++;
2935ad6d6297SScott Long 	}
2936ad6d6297SScott Long 	i=0;
2937ad6d6297SScott Long 	while(i<16) {
293844f05562SScott Long 		*acb_firm_version=bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_version+i);
2939ad6d6297SScott Long 		/* 16 bytes firm_version, 17, 68-83*/
2940ad6d6297SScott Long 		acb_firm_version++;
2941ad6d6297SScott Long 		i++;
2942ad6d6297SScott Long 	}
2943*d74001adSXin LI 	i=0;
2944*d74001adSXin LI 	while(i<16) {
2945*d74001adSXin LI 		*acb_device_map=bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_device_map+i);
2946*d74001adSXin LI 		acb_device_map++;
2947*d74001adSXin LI 		i++;
2948*d74001adSXin LI 	}
2949ad6d6297SScott Long 	printf("ARECA RAID ADAPTER%d: %s \n", acb->pci_unit, ARCMSR_DRIVER_VERSION);
2950ad6d6297SScott Long 	printf("ARECA RAID ADAPTER%d: FIRMWARE VERSION %s \n", acb->pci_unit, acb->firm_version);
2951*d74001adSXin LI 	acb->firm_request_len=CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[1]);   /*firm_request_len, 1, 04-07*/
2952*d74001adSXin LI 	acb->firm_numbers_queue=CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/
2953*d74001adSXin LI 	acb->firm_sdram_size=CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[3]);    /*firm_sdram_size, 3, 12-15*/
2954*d74001adSXin LI 	acb->firm_ide_channels=CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[4]);  /*firm_ide_channels, 4, 16-19*/
2955*d74001adSXin LI 	acb->firm_cfg_version=CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]);	/*firm_cfg_version,  25, 	  */
2956ad6d6297SScott Long 	return;
2957ad6d6297SScott Long }
2958ad6d6297SScott Long /*
2959ad6d6297SScott Long **********************************************************************
296044f05562SScott Long **********************************************************************
296144f05562SScott Long */
296244f05562SScott Long static void arcmsr_get_hbb_config(struct AdapterControlBlock *acb)
296344f05562SScott Long {
296444f05562SScott Long 	char *acb_firm_model=acb->firm_model;
296544f05562SScott Long 	char *acb_firm_version=acb->firm_version;
2966*d74001adSXin LI 	char *acb_device_map = acb->device_map;
2967*d74001adSXin LI 	size_t iop_firm_model=offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]);	/*firm_model,15,60-67*/
2968*d74001adSXin LI 	size_t iop_firm_version=offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]);	/*firm_version,17,68-83*/
2969*d74001adSXin LI 	size_t iop_device_map = offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
297044f05562SScott Long 	int i;
297144f05562SScott Long 
2972*d74001adSXin LI 	CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_MESSAGE_GET_CONFIG);
297344f05562SScott Long 	if(!arcmsr_hbb_wait_msgint_ready(acb)) {
2974*d74001adSXin LI 		printf( "arcmsr%d: wait" "'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit);
297544f05562SScott Long 	}
297644f05562SScott Long 	i=0;
297744f05562SScott Long 	while(i<8) {
297844f05562SScott Long 		*acb_firm_model=bus_space_read_1(acb->btag[1], acb->bhandle[1], iop_firm_model+i);
297944f05562SScott Long 		/* 8 bytes firm_model, 15, 60-67*/
298044f05562SScott Long 		acb_firm_model++;
298144f05562SScott Long 		i++;
298244f05562SScott Long 	}
298344f05562SScott Long 	i=0;
298444f05562SScott Long 	while(i<16) {
298544f05562SScott Long 		*acb_firm_version=bus_space_read_1(acb->btag[1], acb->bhandle[1], iop_firm_version+i);
298644f05562SScott Long 		/* 16 bytes firm_version, 17, 68-83*/
298744f05562SScott Long 		acb_firm_version++;
298844f05562SScott Long 		i++;
298944f05562SScott Long 	}
2990*d74001adSXin LI 	i=0;
2991*d74001adSXin LI 	while(i<16) {
2992*d74001adSXin LI 		*acb_device_map=bus_space_read_1(acb->btag[1], acb->bhandle[1], iop_device_map+i);
2993*d74001adSXin LI 		acb_device_map++;
2994*d74001adSXin LI 		i++;
2995*d74001adSXin LI 	}
299644f05562SScott Long 	printf("ARECA RAID ADAPTER%d: %s \n", acb->pci_unit, ARCMSR_DRIVER_VERSION);
299744f05562SScott Long 	printf("ARECA RAID ADAPTER%d: FIRMWARE VERSION %s \n", acb->pci_unit, acb->firm_version);
2998*d74001adSXin LI 	acb->firm_request_len=CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[1]);   /*firm_request_len, 1, 04-07*/
2999*d74001adSXin LI 	acb->firm_numbers_queue=CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/
3000*d74001adSXin LI 	acb->firm_sdram_size=CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[3]);    /*firm_sdram_size, 3, 12-15*/
3001*d74001adSXin LI 	acb->firm_ide_channels=CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[4]);  /*firm_ide_channels, 4, 16-19*/
3002*d74001adSXin LI 	acb->firm_cfg_version=CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]);	/*firm_cfg_version,  25, 	  */
3003*d74001adSXin LI 	return;
3004*d74001adSXin LI }
3005*d74001adSXin LI /*
3006*d74001adSXin LI **********************************************************************
3007*d74001adSXin LI **********************************************************************
3008*d74001adSXin LI */
3009*d74001adSXin LI static void arcmsr_get_hbc_config(struct AdapterControlBlock *acb)
3010*d74001adSXin LI {
3011*d74001adSXin LI 	char *acb_firm_model=acb->firm_model;
3012*d74001adSXin LI 	char *acb_firm_version=acb->firm_version;
3013*d74001adSXin LI 	char *acb_device_map = acb->device_map;
3014*d74001adSXin LI 	size_t iop_firm_model=offsetof(struct HBC_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]);   /*firm_model,15,60-67*/
3015*d74001adSXin LI 	size_t iop_firm_version=offsetof(struct HBC_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/
3016*d74001adSXin LI 	size_t iop_device_map = offsetof(struct HBC_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
3017*d74001adSXin LI 	int i;
3018*d74001adSXin LI 
3019*d74001adSXin LI 	CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG);
3020*d74001adSXin LI 	CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE);
3021*d74001adSXin LI 	if(!arcmsr_hbc_wait_msgint_ready(acb)) {
3022*d74001adSXin LI 		printf("arcmsr%d: wait 'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit);
3023*d74001adSXin LI 	}
3024*d74001adSXin LI 	i=0;
3025*d74001adSXin LI 	while(i<8) {
3026*d74001adSXin LI 		*acb_firm_model=bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_model+i);
3027*d74001adSXin LI 		/* 8 bytes firm_model, 15, 60-67*/
3028*d74001adSXin LI 		acb_firm_model++;
3029*d74001adSXin LI 		i++;
3030*d74001adSXin LI 	}
3031*d74001adSXin LI 	i=0;
3032*d74001adSXin LI 	while(i<16) {
3033*d74001adSXin LI 		*acb_firm_version=bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_version+i);
3034*d74001adSXin LI 		/* 16 bytes firm_version, 17, 68-83*/
3035*d74001adSXin LI 		acb_firm_version++;
3036*d74001adSXin LI 		i++;
3037*d74001adSXin LI 	}
3038*d74001adSXin LI 	i=0;
3039*d74001adSXin LI 	while(i<16) {
3040*d74001adSXin LI 		*acb_device_map=bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_device_map+i);
3041*d74001adSXin LI 		acb_device_map++;
3042*d74001adSXin LI 		i++;
3043*d74001adSXin LI 	}
3044*d74001adSXin LI 	printf("ARECA RAID ADAPTER%d: %s \n", acb->pci_unit, ARCMSR_DRIVER_VERSION);
3045*d74001adSXin LI 	printf("ARECA RAID ADAPTER%d: FIRMWARE VERSION %s \n", acb->pci_unit, acb->firm_version);
3046*d74001adSXin LI 	acb->firm_request_len	=CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[1]);	/*firm_request_len,   1, 04-07*/
3047*d74001adSXin LI 	acb->firm_numbers_queue	=CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[2]);	/*firm_numbers_queue, 2, 08-11*/
3048*d74001adSXin LI 	acb->firm_sdram_size	=CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[3]);	/*firm_sdram_size,    3, 12-15*/
3049*d74001adSXin LI 	acb->firm_ide_channels	=CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[4]);	/*firm_ide_channels,  4, 16-19*/
3050*d74001adSXin LI 	acb->firm_cfg_version	=CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]);	/*firm_cfg_version,  25, 	  */
305144f05562SScott Long 	return;
305244f05562SScott Long }
305344f05562SScott Long /*
305444f05562SScott Long **********************************************************************
305544f05562SScott Long **********************************************************************
305644f05562SScott Long */
305744f05562SScott Long static void arcmsr_get_firmware_spec(struct AdapterControlBlock *acb)
305844f05562SScott Long {
305944f05562SScott Long 	switch (acb->adapter_type) {
306044f05562SScott Long 	case ACB_ADAPTER_TYPE_A: {
306144f05562SScott Long 			arcmsr_get_hba_config(acb);
306244f05562SScott Long 		}
306344f05562SScott Long 		break;
306444f05562SScott Long 	case ACB_ADAPTER_TYPE_B: {
306544f05562SScott Long 			arcmsr_get_hbb_config(acb);
306644f05562SScott Long 		}
306744f05562SScott Long 		break;
3068*d74001adSXin LI 	case ACB_ADAPTER_TYPE_C: {
3069*d74001adSXin LI 			arcmsr_get_hbc_config(acb);
3070*d74001adSXin LI 		}
3071*d74001adSXin LI 		break;
307244f05562SScott Long 	}
307344f05562SScott Long 	return;
307444f05562SScott Long }
307544f05562SScott Long /*
307644f05562SScott Long **********************************************************************
307744f05562SScott Long **********************************************************************
307844f05562SScott Long */
307944f05562SScott Long static void arcmsr_wait_firmware_ready( struct AdapterControlBlock *acb)
308044f05562SScott Long {
308144f05562SScott Long 	int	timeout=0;
308244f05562SScott Long 
308344f05562SScott Long 	switch (acb->adapter_type) {
308444f05562SScott Long 	case ACB_ADAPTER_TYPE_A: {
3085*d74001adSXin LI 			while ((CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_msgaddr1) & ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK) == 0)
308644f05562SScott Long 			{
308744f05562SScott Long 				if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */
308844f05562SScott Long 				{
3089*d74001adSXin LI 					printf( "arcmsr%d:timed out waiting for firmware \n", acb->pci_unit);
309044f05562SScott Long 					return;
309144f05562SScott Long 				}
309244f05562SScott Long 				UDELAY(15000); /* wait 15 milli-seconds */
309344f05562SScott Long 			}
309444f05562SScott Long 		}
309544f05562SScott Long 		break;
309644f05562SScott Long 	case ACB_ADAPTER_TYPE_B: {
3097*d74001adSXin LI 			while ((CHIP_REG_READ32(HBB_DOORBELL, 0, iop2drv_doorbell) & ARCMSR_MESSAGE_FIRMWARE_OK) == 0)
309844f05562SScott Long 			{
309944f05562SScott Long 				if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */
310044f05562SScott Long 				{
3101*d74001adSXin LI 					printf( "arcmsr%d: timed out waiting for firmware \n", acb->pci_unit);
310244f05562SScott Long 					return;
310344f05562SScott Long 				}
310444f05562SScott Long 				UDELAY(15000); /* wait 15 milli-seconds */
310544f05562SScott Long 			}
3106*d74001adSXin LI 			CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT);
3107*d74001adSXin LI 		}
3108*d74001adSXin LI 		break;
3109*d74001adSXin LI 	case ACB_ADAPTER_TYPE_C: {
3110*d74001adSXin LI 			while ((CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_msgaddr1) & ARCMSR_HBCMU_MESSAGE_FIRMWARE_OK) == 0)
3111*d74001adSXin LI 			{
3112*d74001adSXin LI 				if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */
3113*d74001adSXin LI 				{
3114*d74001adSXin LI 					printf( "arcmsr%d:timed out waiting for firmware ready\n", acb->pci_unit);
3115*d74001adSXin LI 					return;
3116*d74001adSXin LI 				}
3117*d74001adSXin LI 				UDELAY(15000); /* wait 15 milli-seconds */
3118*d74001adSXin LI 			}
311944f05562SScott Long 		}
312044f05562SScott Long 		break;
312144f05562SScott Long 	}
312244f05562SScott Long 	return;
312344f05562SScott Long }
312444f05562SScott Long /*
312544f05562SScott Long **********************************************************************
312644f05562SScott Long **********************************************************************
312744f05562SScott Long */
312844f05562SScott Long static void arcmsr_clear_doorbell_queue_buffer( struct AdapterControlBlock *acb)
312944f05562SScott Long {
3130*d74001adSXin LI 	u_int32_t outbound_doorbell;
3131*d74001adSXin LI 
313244f05562SScott Long 	switch (acb->adapter_type) {
313344f05562SScott Long 	case ACB_ADAPTER_TYPE_A: {
313444f05562SScott Long 			/* empty doorbell Qbuffer if door bell ringed */
3135*d74001adSXin LI 			outbound_doorbell = CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_doorbell);
3136*d74001adSXin LI 			CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_doorbell, outbound_doorbell);	/*clear doorbell interrupt */
3137*d74001adSXin LI 			CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK);
3138*d74001adSXin LI 
313944f05562SScott Long 		}
314044f05562SScott Long 		break;
314144f05562SScott Long 	case ACB_ADAPTER_TYPE_B: {
3142*d74001adSXin LI 			CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell, ARCMSR_MESSAGE_INT_CLEAR_PATTERN);/*clear interrupt and message state*/
3143*d74001adSXin LI 			CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_READ_OK);
314444f05562SScott Long 			/* let IOP know data has been read */
314544f05562SScott Long 		}
314644f05562SScott Long 		break;
3147*d74001adSXin LI 	case ACB_ADAPTER_TYPE_C: {
3148*d74001adSXin LI 			/* empty doorbell Qbuffer if door bell ringed */
3149*d74001adSXin LI 			outbound_doorbell = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell);
3150*d74001adSXin LI 			CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, outbound_doorbell);	/*clear doorbell interrupt */
3151*d74001adSXin LI 			CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK);
3152*d74001adSXin LI 
3153*d74001adSXin LI 		}
3154*d74001adSXin LI 		break;
315544f05562SScott Long 	}
315644f05562SScott Long 	return;
315744f05562SScott Long }
315844f05562SScott Long /*
315944f05562SScott Long ************************************************************************
316044f05562SScott Long ************************************************************************
316144f05562SScott Long */
316244f05562SScott Long static u_int32_t arcmsr_iop_confirm(struct AdapterControlBlock *acb)
316344f05562SScott Long {
316444f05562SScott Long 	unsigned long srb_phyaddr;
316544f05562SScott Long 	u_int32_t srb_phyaddr_hi32;
316644f05562SScott Long 
316744f05562SScott Long 	/*
316844f05562SScott Long 	********************************************************************
316944f05562SScott Long 	** here we need to tell iop 331 our freesrb.HighPart
317044f05562SScott Long 	** if freesrb.HighPart is not zero
317144f05562SScott Long 	********************************************************************
317244f05562SScott Long 	*/
3173*d74001adSXin LI 	srb_phyaddr= (unsigned long) acb->srb_phyaddr.phyaddr;
3174*d74001adSXin LI //	srb_phyaddr_hi32=(u_int32_t) ((srb_phyaddr>>16)>>16);
3175*d74001adSXin LI 	srb_phyaddr_hi32=acb->srb_phyaddr.B.phyadd_high;
317644f05562SScott Long 	switch (acb->adapter_type) {
317744f05562SScott Long 	case ACB_ADAPTER_TYPE_A: {
317844f05562SScott Long 			if(srb_phyaddr_hi32!=0) {
3179*d74001adSXin LI 				CHIP_REG_WRITE32(HBA_MessageUnit, 0, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG);
3180*d74001adSXin LI 				CHIP_REG_WRITE32(HBA_MessageUnit, 0, msgcode_rwbuffer[1], srb_phyaddr_hi32);
3181*d74001adSXin LI 				CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG);
318244f05562SScott Long 				if(!arcmsr_hba_wait_msgint_ready(acb)) {
3183*d74001adSXin LI 					printf( "arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit);
318444f05562SScott Long 					return FALSE;
318544f05562SScott Long 				}
318644f05562SScott Long 			}
318744f05562SScott Long 		}
318844f05562SScott Long 		break;
318944f05562SScott Long 		/*
319044f05562SScott Long 		***********************************************************************
319144f05562SScott Long 		**    if adapter type B, set window of "post command Q"
319244f05562SScott Long 		***********************************************************************
319344f05562SScott Long 		*/
319444f05562SScott Long 	case ACB_ADAPTER_TYPE_B: {
319544f05562SScott Long 			u_int32_t post_queue_phyaddr;
319644f05562SScott Long 			struct HBB_MessageUnit *phbbmu;
319744f05562SScott Long 
319844f05562SScott Long 			phbbmu=(struct HBB_MessageUnit *)acb->pmu;
319944f05562SScott Long 			phbbmu->postq_index=0;
320044f05562SScott Long 			phbbmu->doneq_index=0;
3201*d74001adSXin LI 			CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_MESSAGE_SET_POST_WINDOW);
320244f05562SScott Long 			if(!arcmsr_hbb_wait_msgint_ready(acb)) {
3203*d74001adSXin LI 				printf( "arcmsr%d: 'set window of post command Q' timeout\n", acb->pci_unit);
320444f05562SScott Long 				return FALSE;
320544f05562SScott Long 			}
3206*d74001adSXin LI 			post_queue_phyaddr = srb_phyaddr + ARCMSR_MAX_FREESRB_NUM*sizeof(struct CommandControlBlock)
320744f05562SScott Long 			+ offsetof(struct HBB_MessageUnit, post_qbuffer);
3208*d74001adSXin LI 			CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG); /* driver "set config" signature */
3209*d74001adSXin LI 			CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[1], srb_phyaddr_hi32); /* normal should be zero */
3210*d74001adSXin LI 			CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[2], post_queue_phyaddr); /* postQ size (256+8)*4 */
3211*d74001adSXin LI 			CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[3], post_queue_phyaddr+1056); /* doneQ size (256+8)*4 */
3212*d74001adSXin LI 			CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[4], 1056); /* srb maxQ size must be --> [(256+8)*4] */
3213*d74001adSXin LI 			CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_MESSAGE_SET_CONFIG);
321444f05562SScott Long 			if(!arcmsr_hbb_wait_msgint_ready(acb)) {
321544f05562SScott Long 				printf( "arcmsr%d: 'set command Q window' timeout \n", acb->pci_unit);
321644f05562SScott Long 				return FALSE;
321744f05562SScott Long 			}
3218*d74001adSXin LI 			CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_MESSAGE_START_DRIVER_MODE);
321944f05562SScott Long 			if(!arcmsr_hbb_wait_msgint_ready(acb)) {
322044f05562SScott Long 				printf( "arcmsr%d: 'start diver mode' timeout \n", acb->pci_unit);
322144f05562SScott Long 				return FALSE;
322244f05562SScott Long 			}
322344f05562SScott Long 		}
322444f05562SScott Long 		break;
3225*d74001adSXin LI 	case ACB_ADAPTER_TYPE_C: {
3226*d74001adSXin LI 			if(srb_phyaddr_hi32!=0) {
3227*d74001adSXin LI 				CHIP_REG_WRITE32(HBC_MessageUnit, 0, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG);
3228*d74001adSXin LI 				CHIP_REG_WRITE32(HBC_MessageUnit, 0, msgcode_rwbuffer[1], srb_phyaddr_hi32);
3229*d74001adSXin LI 				CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG);
3230*d74001adSXin LI 				CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell,ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE);
3231*d74001adSXin LI 				if(!arcmsr_hbc_wait_msgint_ready(acb)) {
3232*d74001adSXin LI 					printf( "arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit);
3233*d74001adSXin LI 					return FALSE;
3234*d74001adSXin LI 				}
3235*d74001adSXin LI 			}
3236*d74001adSXin LI 		}
3237*d74001adSXin LI 		break;
323844f05562SScott Long 	}
323944f05562SScott Long 	return TRUE;
324044f05562SScott Long }
324144f05562SScott Long /*
324244f05562SScott Long ************************************************************************
324344f05562SScott Long ************************************************************************
324444f05562SScott Long */
324544f05562SScott Long static void arcmsr_enable_eoi_mode(struct AdapterControlBlock *acb)
324644f05562SScott Long {
324744f05562SScott Long 	switch (acb->adapter_type)
324844f05562SScott Long 	{
324944f05562SScott Long 	case ACB_ADAPTER_TYPE_A:
3250*d74001adSXin LI 	case ACB_ADAPTER_TYPE_C:
3251*d74001adSXin LI 		break;
325244f05562SScott Long 	case ACB_ADAPTER_TYPE_B: {
3253*d74001adSXin LI 			CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell,ARCMSR_MESSAGE_ACTIVE_EOI_MODE);
325444f05562SScott Long 			if(!arcmsr_hbb_wait_msgint_ready(acb)) {
3255*d74001adSXin LI 				printf( "arcmsr%d: 'iop enable eoi mode' timeout \n", acb->pci_unit);
3256*d74001adSXin LI 
325744f05562SScott Long 				return;
325844f05562SScott Long 			}
325944f05562SScott Long 		}
326044f05562SScott Long 		break;
326144f05562SScott Long 	}
326244f05562SScott Long 	return;
326344f05562SScott Long }
326444f05562SScott Long /*
326544f05562SScott Long **********************************************************************
3266ad6d6297SScott Long **********************************************************************
3267ad6d6297SScott Long */
3268ad6d6297SScott Long static void arcmsr_iop_init(struct AdapterControlBlock *acb)
3269ad6d6297SScott Long {
327044f05562SScott Long 	u_int32_t intmask_org;
3271ad6d6297SScott Long 
327244f05562SScott Long 	/* disable all outbound interrupt */
327344f05562SScott Long 	intmask_org=arcmsr_disable_allintr(acb);
327444f05562SScott Long 	arcmsr_wait_firmware_ready(acb);
327544f05562SScott Long 	arcmsr_iop_confirm(acb);
3276ad6d6297SScott Long 	arcmsr_get_firmware_spec(acb);
327744f05562SScott Long 	/*start background rebuild*/
3278ad6d6297SScott Long 	arcmsr_start_adapter_bgrb(acb);
327944f05562SScott Long 	/* empty doorbell Qbuffer if door bell ringed */
328044f05562SScott Long 	arcmsr_clear_doorbell_queue_buffer(acb);
328144f05562SScott Long 	arcmsr_enable_eoi_mode(acb);
328244f05562SScott Long 	/* enable outbound Post Queue, outbound doorbell Interrupt */
328344f05562SScott Long 	arcmsr_enable_allintr(acb, intmask_org);
3284ad6d6297SScott Long 	acb->acb_flags |=ACB_F_IOP_INITED;
3285ad6d6297SScott Long 	return;
3286ad6d6297SScott Long }
3287ad6d6297SScott Long /*
3288ad6d6297SScott Long **********************************************************************
3289f1c579b1SScott Long **********************************************************************
3290f1c579b1SScott Long */
3291f1c579b1SScott Long static void arcmsr_map_freesrb(void *arg, bus_dma_segment_t *segs, int nseg, int error)
3292f1c579b1SScott Long {
3293ad6d6297SScott Long 	struct AdapterControlBlock *acb=arg;
3294ad6d6297SScott Long 	struct CommandControlBlock *srb_tmp;
3295ad6d6297SScott Long 	u_int8_t * dma_memptr;
329644f05562SScott Long 	u_int32_t i;
3297ad6d6297SScott Long 	unsigned long srb_phyaddr=(unsigned long)segs->ds_addr;
3298f1c579b1SScott Long 
3299ad6d6297SScott Long 	dma_memptr=acb->uncacheptr;
3300*d74001adSXin LI 	acb->srb_phyaddr.phyaddr=srb_phyaddr;
3301ad6d6297SScott Long 	srb_tmp=(struct CommandControlBlock *)dma_memptr;
3302ad6d6297SScott Long 	for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++) {
330344f05562SScott Long 		if(bus_dmamap_create(acb->dm_segs_dmat,
330444f05562SScott Long 			 /*flags*/0, &srb_tmp->dm_segs_dmamap)!=0) {
3305ad6d6297SScott Long 			acb->acb_flags |= ACB_F_MAPFREESRB_FAILD;
330644f05562SScott Long 			printf("arcmsr%d:"
330744f05562SScott Long 			" srb dmamap bus_dmamap_create error\n", acb->pci_unit);
3308ad6d6297SScott Long 			return;
3309ad6d6297SScott Long 		}
3310*d74001adSXin LI 		srb_tmp->cdb_shifted_phyaddr=(acb->adapter_type==ACB_ADAPTER_TYPE_C)?srb_phyaddr:(srb_phyaddr >> 5);
3311ad6d6297SScott Long 		srb_tmp->acb=acb;
3312ad6d6297SScott Long 		acb->srbworkingQ[i]=acb->psrb_pool[i]=srb_tmp;
3313ad6d6297SScott Long 		srb_phyaddr=srb_phyaddr+sizeof(struct CommandControlBlock);
3314ad6d6297SScott Long 		srb_tmp++;
3315ad6d6297SScott Long 	}
3316ad6d6297SScott Long 	acb->vir2phy_offset=(unsigned long)srb_tmp-(unsigned long)srb_phyaddr;
3317f1c579b1SScott Long 	return;
3318f1c579b1SScott Long }
3319f1c579b1SScott Long /*
3320f1c579b1SScott Long ************************************************************************
3321f1c579b1SScott Long **
3322f1c579b1SScott Long **
3323f1c579b1SScott Long ************************************************************************
3324f1c579b1SScott Long */
3325ad6d6297SScott Long static void arcmsr_free_resource(struct AdapterControlBlock *acb)
3326f1c579b1SScott Long {
3327f1c579b1SScott Long 	/* remove the control device */
3328ad6d6297SScott Long 	if(acb->ioctl_dev != NULL) {
3329ad6d6297SScott Long 		destroy_dev(acb->ioctl_dev);
3330f1c579b1SScott Long 	}
3331ad6d6297SScott Long 	bus_dmamap_unload(acb->srb_dmat, acb->srb_dmamap);
3332ad6d6297SScott Long 	bus_dmamap_destroy(acb->srb_dmat, acb->srb_dmamap);
3333ad6d6297SScott Long 	bus_dma_tag_destroy(acb->srb_dmat);
3334ad6d6297SScott Long 	bus_dma_tag_destroy(acb->dm_segs_dmat);
3335ad6d6297SScott Long 	bus_dma_tag_destroy(acb->parent_dmat);
3336f1c579b1SScott Long 	return;
3337f1c579b1SScott Long }
3338f1c579b1SScott Long /*
3339f1c579b1SScott Long ************************************************************************
3340f1c579b1SScott Long ************************************************************************
3341f1c579b1SScott Long */
3342ad6d6297SScott Long static u_int32_t arcmsr_initialize(device_t dev)
3343f1c579b1SScott Long {
3344ad6d6297SScott Long 	struct AdapterControlBlock *acb=device_get_softc(dev);
3345ad6d6297SScott Long 	u_int16_t pci_command;
334644f05562SScott Long 	int i, j,max_coherent_size;
3347f1c579b1SScott Long 
334844f05562SScott Long 	switch (pci_get_devid(dev)) {
3349*d74001adSXin LI 	case PCIDevVenIDARC1880: {
3350*d74001adSXin LI 			acb->adapter_type=ACB_ADAPTER_TYPE_C;
3351*d74001adSXin LI 			max_coherent_size=ARCMSR_SRBS_POOL_SIZE;
3352*d74001adSXin LI 		}
3353*d74001adSXin LI 		break;
335444f05562SScott Long 	case PCIDevVenIDARC1201: {
335544f05562SScott Long 			acb->adapter_type=ACB_ADAPTER_TYPE_B;
3356*d74001adSXin LI 			max_coherent_size=ARCMSR_SRBS_POOL_SIZE+(sizeof(struct HBB_MessageUnit));
335744f05562SScott Long 		}
335844f05562SScott Long 		break;
335944f05562SScott Long 	case PCIDevVenIDARC1110:
336044f05562SScott Long 	case PCIDevVenIDARC1120:
336144f05562SScott Long 	case PCIDevVenIDARC1130:
336244f05562SScott Long 	case PCIDevVenIDARC1160:
336344f05562SScott Long 	case PCIDevVenIDARC1170:
336444f05562SScott Long 	case PCIDevVenIDARC1210:
336544f05562SScott Long 	case PCIDevVenIDARC1220:
336644f05562SScott Long 	case PCIDevVenIDARC1230:
336744f05562SScott Long 	case PCIDevVenIDARC1260:
336844f05562SScott Long 	case PCIDevVenIDARC1270:
336944f05562SScott Long 	case PCIDevVenIDARC1280:
3370*d74001adSXin LI 	case PCIDevVenIDARC1212:
3371*d74001adSXin LI 	case PCIDevVenIDARC1222:
337244f05562SScott Long 	case PCIDevVenIDARC1380:
337344f05562SScott Long 	case PCIDevVenIDARC1381:
337444f05562SScott Long 	case PCIDevVenIDARC1680:
337544f05562SScott Long 	case PCIDevVenIDARC1681: {
337644f05562SScott Long 			acb->adapter_type=ACB_ADAPTER_TYPE_A;
337744f05562SScott Long 			max_coherent_size=ARCMSR_SRBS_POOL_SIZE;
337844f05562SScott Long 		}
337944f05562SScott Long 		break;
338044f05562SScott Long 	default: {
338144f05562SScott Long 			printf("arcmsr%d:"
338244f05562SScott Long 			" unknown RAID adapter type \n", device_get_unit(dev));
338344f05562SScott Long 			return ENOMEM;
338444f05562SScott Long 		}
338544f05562SScott Long 	}
3386f1c579b1SScott Long #if __FreeBSD_version >= 502010
3387f1c579b1SScott Long 	if(bus_dma_tag_create(  /*parent*/	NULL,
3388f1c579b1SScott Long 				/*alignemnt*/	1,
3389f1c579b1SScott Long 				/*boundary*/	0,
3390701d9f1fSScott Long 				/*lowaddr*/	BUS_SPACE_MAXADDR,
3391f1c579b1SScott Long 				/*highaddr*/	BUS_SPACE_MAXADDR,
3392f1c579b1SScott Long 				/*filter*/	NULL,
3393f1c579b1SScott Long 				/*filterarg*/	NULL,
3394f1c579b1SScott Long 				/*maxsize*/	BUS_SPACE_MAXSIZE_32BIT,
3395f1c579b1SScott Long 				/*nsegments*/	BUS_SPACE_UNRESTRICTED,
3396f1c579b1SScott Long 				/*maxsegsz*/	BUS_SPACE_MAXSIZE_32BIT,
3397f1c579b1SScott Long 				/*flags*/	0,
3398f1c579b1SScott Long 				/*lockfunc*/	NULL,
3399f1c579b1SScott Long 				/*lockarg*/	NULL,
3400ad6d6297SScott Long 						&acb->parent_dmat) != 0)
3401f1c579b1SScott Long #else
3402f1c579b1SScott Long 	if(bus_dma_tag_create(  /*parent*/	NULL,
3403f1c579b1SScott Long 				/*alignemnt*/	1,
3404f1c579b1SScott Long 				/*boundary*/	0,
3405701d9f1fSScott Long 				/*lowaddr*/	BUS_SPACE_MAXADDR,
3406f1c579b1SScott Long 				/*highaddr*/	BUS_SPACE_MAXADDR,
3407f1c579b1SScott Long 				/*filter*/	NULL,
3408f1c579b1SScott Long 				/*filterarg*/	NULL,
3409f1c579b1SScott Long 				/*maxsize*/	BUS_SPACE_MAXSIZE_32BIT,
3410f1c579b1SScott Long 				/*nsegments*/	BUS_SPACE_UNRESTRICTED,
3411f1c579b1SScott Long 				/*maxsegsz*/	BUS_SPACE_MAXSIZE_32BIT,
3412f1c579b1SScott Long 				/*flags*/	0,
3413ad6d6297SScott Long 						&acb->parent_dmat) != 0)
3414f1c579b1SScott Long #endif
3415f1c579b1SScott Long 	{
341644f05562SScott Long 		printf("arcmsr%d: parent_dmat bus_dma_tag_create failure!\n", device_get_unit(dev));
3417f1c579b1SScott Long 		return ENOMEM;
3418f1c579b1SScott Long 	}
3419f1c579b1SScott Long 	/* Create a single tag describing a region large enough to hold all of the s/g lists we will need. */
3420f1c579b1SScott Long #if __FreeBSD_version >= 502010
3421ad6d6297SScott Long 	if(bus_dma_tag_create(  /*parent_dmat*/	acb->parent_dmat,
3422f1c579b1SScott Long 				/*alignment*/	1,
3423f1c579b1SScott Long 				/*boundary*/	0,
3424f1c579b1SScott Long 				/*lowaddr*/	BUS_SPACE_MAXADDR,
3425f1c579b1SScott Long 				/*highaddr*/	BUS_SPACE_MAXADDR,
3426f1c579b1SScott Long 				/*filter*/	NULL,
3427f1c579b1SScott Long 				/*filterarg*/	NULL,
3428f1c579b1SScott Long 				/*maxsize*/	MAXBSIZE,
3429f1c579b1SScott Long 				/*nsegments*/	ARCMSR_MAX_SG_ENTRIES,
3430f1c579b1SScott Long 				/*maxsegsz*/	BUS_SPACE_MAXSIZE_32BIT,
3431ad6d6297SScott Long 				/*flags*/	0,
3432f1c579b1SScott Long 				/*lockfunc*/	busdma_lock_mutex,
3433579ec1a5SScott Long 	#if __FreeBSD_version >= 700025
34345878cbecSScott Long 				/*lockarg*/	&acb->qbuffer_lock,
3435579ec1a5SScott Long 	#else
3436579ec1a5SScott Long 				/*lockarg*/	&Giant,
3437579ec1a5SScott Long 	#endif
3438ad6d6297SScott Long 						&acb->dm_segs_dmat) != 0)
3439f1c579b1SScott Long #else
3440ad6d6297SScott Long 	if(bus_dma_tag_create(  /*parent_dmat*/	acb->parent_dmat,
3441f1c579b1SScott Long 				/*alignment*/	1,
3442f1c579b1SScott Long 				/*boundary*/	0,
3443f1c579b1SScott Long 				/*lowaddr*/	BUS_SPACE_MAXADDR,
3444f1c579b1SScott Long 				/*highaddr*/	BUS_SPACE_MAXADDR,
3445f1c579b1SScott Long 				/*filter*/	NULL,
3446f1c579b1SScott Long 				/*filterarg*/	NULL,
3447f1c579b1SScott Long 				/*maxsize*/	MAXBSIZE,
3448f1c579b1SScott Long 				/*nsegments*/	ARCMSR_MAX_SG_ENTRIES,
3449f1c579b1SScott Long 				/*maxsegsz*/	BUS_SPACE_MAXSIZE_32BIT,
3450ad6d6297SScott Long 				/*flags*/	0,
3451ad6d6297SScott Long 						&acb->dm_segs_dmat) != 0)
3452f1c579b1SScott Long #endif
3453f1c579b1SScott Long 	{
3454ad6d6297SScott Long 		bus_dma_tag_destroy(acb->parent_dmat);
345544f05562SScott Long 		printf("arcmsr%d: dm_segs_dmat bus_dma_tag_create failure!\n", device_get_unit(dev));
3456f1c579b1SScott Long 		return ENOMEM;
3457f1c579b1SScott Long 	}
3458ad6d6297SScott Long 	/* DMA tag for our srb structures.... Allocate the freesrb memory */
3459f1c579b1SScott Long #if __FreeBSD_version >= 502010
3460ad6d6297SScott Long 	if(bus_dma_tag_create(  /*parent_dmat*/	acb->parent_dmat,
346144f05562SScott Long 				/*alignment*/	0x20,
3462f1c579b1SScott Long 				/*boundary*/	0,
3463f1c579b1SScott Long 				/*lowaddr*/	BUS_SPACE_MAXADDR_32BIT,
3464f1c579b1SScott Long 				/*highaddr*/	BUS_SPACE_MAXADDR,
3465f1c579b1SScott Long 				/*filter*/	NULL,
3466f1c579b1SScott Long 				/*filterarg*/	NULL,
346744f05562SScott Long 				/*maxsize*/	max_coherent_size,
3468f1c579b1SScott Long 				/*nsegments*/	1,
3469f1c579b1SScott Long 				/*maxsegsz*/	BUS_SPACE_MAXSIZE_32BIT,
3470701d9f1fSScott Long 				/*flags*/	0,
3471f1c579b1SScott Long 				/*lockfunc*/	NULL,
3472f1c579b1SScott Long 				/*lockarg*/	NULL,
3473ad6d6297SScott Long 						&acb->srb_dmat) != 0)
3474f1c579b1SScott Long #else
3475ad6d6297SScott Long 	if(bus_dma_tag_create(  /*parent_dmat*/	acb->parent_dmat,
347644f05562SScott Long 				/*alignment*/	0x20,
3477f1c579b1SScott Long 				/*boundary*/	0,
3478f1c579b1SScott Long 				/*lowaddr*/	BUS_SPACE_MAXADDR_32BIT,
3479f1c579b1SScott Long 				/*highaddr*/	BUS_SPACE_MAXADDR,
3480f1c579b1SScott Long 				/*filter*/	NULL,
3481f1c579b1SScott Long 				/*filterarg*/	NULL,
348244f05562SScott Long 				/*maxsize*/	max_coherent_size,
3483f1c579b1SScott Long 				/*nsegments*/	1,
3484f1c579b1SScott Long 				/*maxsegsz*/	BUS_SPACE_MAXSIZE_32BIT,
3485701d9f1fSScott Long 				/*flags*/	0,
3486ad6d6297SScott Long 						&acb->srb_dmat) != 0)
3487f1c579b1SScott Long #endif
3488f1c579b1SScott Long 	{
3489ad6d6297SScott Long 		bus_dma_tag_destroy(acb->dm_segs_dmat);
3490ad6d6297SScott Long 		bus_dma_tag_destroy(acb->parent_dmat);
349144f05562SScott Long 		printf("arcmsr%d: srb_dmat bus_dma_tag_create failure!\n", device_get_unit(dev));
3492f1c579b1SScott Long 		return ENXIO;
3493f1c579b1SScott Long 	}
3494f1c579b1SScott Long 	/* Allocation for our srbs */
3495*d74001adSXin LI 	if(bus_dmamem_alloc(acb->srb_dmat, (void **)&acb->uncacheptr, BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_ZERO, &acb->srb_dmamap) != 0) {
3496ad6d6297SScott Long 		bus_dma_tag_destroy(acb->srb_dmat);
3497ad6d6297SScott Long 		bus_dma_tag_destroy(acb->dm_segs_dmat);
3498ad6d6297SScott Long 		bus_dma_tag_destroy(acb->parent_dmat);
349944f05562SScott Long 		printf("arcmsr%d: srb_dmat bus_dmamem_alloc failure!\n", device_get_unit(dev));
3500f1c579b1SScott Long 		return ENXIO;
3501f1c579b1SScott Long 	}
3502f1c579b1SScott Long 	/* And permanently map them */
3503*d74001adSXin LI 	if(bus_dmamap_load(acb->srb_dmat, acb->srb_dmamap, acb->uncacheptr, max_coherent_size, arcmsr_map_freesrb, acb, /*flags*/0)) {
3504ad6d6297SScott Long 		bus_dma_tag_destroy(acb->srb_dmat);
3505ad6d6297SScott Long 		bus_dma_tag_destroy(acb->dm_segs_dmat);
3506ad6d6297SScott Long 		bus_dma_tag_destroy(acb->parent_dmat);
350744f05562SScott Long 		printf("arcmsr%d: srb_dmat bus_dmamap_load failure!\n", device_get_unit(dev));
3508f1c579b1SScott Long 		return ENXIO;
3509f1c579b1SScott Long 	}
3510f1c579b1SScott Long 	pci_command=pci_read_config(dev, PCIR_COMMAND, 2);
3511f1c579b1SScott Long 	pci_command |= PCIM_CMD_BUSMASTEREN;
3512f1c579b1SScott Long 	pci_command |= PCIM_CMD_PERRESPEN;
3513f1c579b1SScott Long 	pci_command |= PCIM_CMD_MWRICEN;
3514f1c579b1SScott Long 	/* Enable Busmaster/Mem */
3515f1c579b1SScott Long 	pci_command |= PCIM_CMD_MEMEN;
3516f1c579b1SScott Long 	pci_write_config(dev, PCIR_COMMAND, pci_command, 2);
351744f05562SScott Long 	switch(acb->adapter_type) {
351844f05562SScott Long 	case ACB_ADAPTER_TYPE_A: {
351944f05562SScott Long 			u_int32_t rid0=PCIR_BAR(0);
352044f05562SScott Long 			vm_offset_t	mem_base0;
352144f05562SScott Long 
3522*d74001adSXin LI 			acb->sys_res_arcmsr[0]=bus_alloc_resource(dev,SYS_RES_MEMORY, &rid0, 0ul, ~0ul, 0x1000, RF_ACTIVE);
352344f05562SScott Long 			if(acb->sys_res_arcmsr[0] == NULL) {
3524ad6d6297SScott Long 				arcmsr_free_resource(acb);
3525*d74001adSXin LI 				printf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev));
3526f1c579b1SScott Long 				return ENOMEM;
3527f1c579b1SScott Long 			}
352844f05562SScott Long 			if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) {
3529ad6d6297SScott Long 				arcmsr_free_resource(acb);
3530*d74001adSXin LI 				printf("arcmsr%d: rman_get_start failure!\n", device_get_unit(dev));
3531f1c579b1SScott Long 				return ENXIO;
3532f1c579b1SScott Long 			}
353344f05562SScott Long 			mem_base0=(vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]);
353444f05562SScott Long 			if(mem_base0==0) {
3535ad6d6297SScott Long 				arcmsr_free_resource(acb);
3536*d74001adSXin LI 				printf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev));
3537f1c579b1SScott Long 				return ENXIO;
3538f1c579b1SScott Long 			}
353944f05562SScott Long 			acb->btag[0]=rman_get_bustag(acb->sys_res_arcmsr[0]);
354044f05562SScott Long 			acb->bhandle[0]=rman_get_bushandle(acb->sys_res_arcmsr[0]);
354144f05562SScott Long 			acb->pmu=(struct MessageUnit_UNION *)mem_base0;
354244f05562SScott Long 		}
354344f05562SScott Long 		break;
354444f05562SScott Long 	case ACB_ADAPTER_TYPE_B: {
354544f05562SScott Long 			struct HBB_MessageUnit *phbbmu;
354644f05562SScott Long 			struct CommandControlBlock *freesrb;
354744f05562SScott Long 			u_int32_t rid[]={ PCIR_BAR(0), PCIR_BAR(2) };
354844f05562SScott Long 			vm_offset_t	mem_base[]={0,0};
354944f05562SScott Long 			for(i=0; i<2; i++) {
355044f05562SScott Long 				if(i==0) {
3551*d74001adSXin LI 					acb->sys_res_arcmsr[i]=bus_alloc_resource(dev,SYS_RES_MEMORY, &rid[i],
3552*d74001adSXin LI 											0x20400, 0x20400+sizeof(struct HBB_DOORBELL), sizeof(struct HBB_DOORBELL), RF_ACTIVE);
355344f05562SScott Long 				} else {
3554*d74001adSXin LI 					acb->sys_res_arcmsr[i]=bus_alloc_resource(dev, SYS_RES_MEMORY, &rid[i],
3555*d74001adSXin LI 											0x0fa00, 0x0fa00+sizeof(struct HBB_RWBUFFER), sizeof(struct HBB_RWBUFFER), RF_ACTIVE);
355644f05562SScott Long 				}
355744f05562SScott Long 				if(acb->sys_res_arcmsr[i] == NULL) {
355844f05562SScott Long 					arcmsr_free_resource(acb);
3559*d74001adSXin LI 					printf("arcmsr%d: bus_alloc_resource %d failure!\n", device_get_unit(dev), i);
356044f05562SScott Long 					return ENOMEM;
356144f05562SScott Long 				}
356244f05562SScott Long 				if(rman_get_start(acb->sys_res_arcmsr[i]) <= 0) {
356344f05562SScott Long 					arcmsr_free_resource(acb);
3564*d74001adSXin LI 					printf("arcmsr%d: rman_get_start %d failure!\n", device_get_unit(dev), i);
356544f05562SScott Long 					return ENXIO;
356644f05562SScott Long 				}
356744f05562SScott Long 				mem_base[i]=(vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[i]);
356844f05562SScott Long 				if(mem_base[i]==0) {
356944f05562SScott Long 					arcmsr_free_resource(acb);
3570*d74001adSXin LI 					printf("arcmsr%d: rman_get_virtual %d failure!\n", device_get_unit(dev), i);
357144f05562SScott Long 					return ENXIO;
357244f05562SScott Long 				}
357344f05562SScott Long 				acb->btag[i]=rman_get_bustag(acb->sys_res_arcmsr[i]);
357444f05562SScott Long 				acb->bhandle[i]=rman_get_bushandle(acb->sys_res_arcmsr[i]);
357544f05562SScott Long 			}
357644f05562SScott Long 			freesrb=(struct CommandControlBlock *)acb->uncacheptr;
357744f05562SScott Long 			acb->pmu=(struct MessageUnit_UNION *)&freesrb[ARCMSR_MAX_FREESRB_NUM];
357844f05562SScott Long 			phbbmu=(struct HBB_MessageUnit *)acb->pmu;
357944f05562SScott Long 			phbbmu->hbb_doorbell=(struct HBB_DOORBELL *)mem_base[0];
358044f05562SScott Long 			phbbmu->hbb_rwbuffer=(struct HBB_RWBUFFER *)mem_base[1];
358144f05562SScott Long 		}
358244f05562SScott Long 		break;
3583*d74001adSXin LI 	case ACB_ADAPTER_TYPE_C: {
3584*d74001adSXin LI 			u_int32_t rid0=PCIR_BAR(1);
3585*d74001adSXin LI 			vm_offset_t	mem_base0;
3586*d74001adSXin LI 
3587*d74001adSXin LI 			acb->sys_res_arcmsr[0]=bus_alloc_resource(dev,SYS_RES_MEMORY, &rid0, 0ul, ~0ul, sizeof(struct HBC_MessageUnit), RF_ACTIVE);
3588*d74001adSXin LI 			if(acb->sys_res_arcmsr[0] == NULL) {
3589*d74001adSXin LI 				arcmsr_free_resource(acb);
3590*d74001adSXin LI 				printf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev));
3591*d74001adSXin LI 				return ENOMEM;
3592*d74001adSXin LI 			}
3593*d74001adSXin LI 			if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) {
3594*d74001adSXin LI 				arcmsr_free_resource(acb);
3595*d74001adSXin LI 				printf("arcmsr%d: rman_get_start failure!\n", device_get_unit(dev));
3596*d74001adSXin LI 				return ENXIO;
3597*d74001adSXin LI 			}
3598*d74001adSXin LI 			mem_base0=(vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]);
3599*d74001adSXin LI 			if(mem_base0==0) {
3600*d74001adSXin LI 				arcmsr_free_resource(acb);
3601*d74001adSXin LI 				printf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev));
3602*d74001adSXin LI 				return ENXIO;
3603*d74001adSXin LI 			}
3604*d74001adSXin LI 			acb->btag[0]=rman_get_bustag(acb->sys_res_arcmsr[0]);
3605*d74001adSXin LI 			acb->bhandle[0]=rman_get_bushandle(acb->sys_res_arcmsr[0]);
3606*d74001adSXin LI 			acb->pmu=(struct MessageUnit_UNION *)mem_base0;
3607*d74001adSXin LI 		}
3608*d74001adSXin LI 		break;
360944f05562SScott Long 	}
3610ad6d6297SScott Long 	if(acb->acb_flags & ACB_F_MAPFREESRB_FAILD) {
3611ad6d6297SScott Long 		arcmsr_free_resource(acb);
361244f05562SScott Long 		printf("arcmsr%d: map free srb failure!\n", device_get_unit(dev));
3613f1c579b1SScott Long 		return ENXIO;
3614f1c579b1SScott Long 	}
3615*d74001adSXin LI 	acb->acb_flags  |= (ACB_F_MESSAGE_WQBUFFER_CLEARED|ACB_F_MESSAGE_RQBUFFER_CLEARED|ACB_F_MESSAGE_WQBUFFER_READ);
3616ad6d6297SScott Long 	acb->acb_flags &= ~ACB_F_SCSISTOPADAPTER;
3617ad6d6297SScott Long 	/*
3618ad6d6297SScott Long 	********************************************************************
3619ad6d6297SScott Long 	** init raid volume state
3620ad6d6297SScott Long 	********************************************************************
3621ad6d6297SScott Long 	*/
3622ad6d6297SScott Long 	for(i=0;i<ARCMSR_MAX_TARGETID;i++) {
3623ad6d6297SScott Long 		for(j=0;j<ARCMSR_MAX_TARGETLUN;j++) {
362444f05562SScott Long 			acb->devstate[i][j]=ARECA_RAID_GONE;
3625ad6d6297SScott Long 		}
3626ad6d6297SScott Long 	}
3627ad6d6297SScott Long 	arcmsr_iop_init(acb);
3628f1c579b1SScott Long 	return(0);
3629f1c579b1SScott Long }
3630f1c579b1SScott Long /*
3631f1c579b1SScott Long ************************************************************************
3632f1c579b1SScott Long ************************************************************************
3633f1c579b1SScott Long */
3634f2aa0e9fSWarner Losh static int arcmsr_attach(device_t dev)
3635f1c579b1SScott Long {
3636ad6d6297SScott Long 	struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev);
3637ad6d6297SScott Long 	u_int32_t unit=device_get_unit(dev);
3638f1c579b1SScott Long 	struct ccb_setasync csa;
3639f1c579b1SScott Long 	struct cam_devq	*devq;	/* Device Queue to use for this SIM */
3640f1c579b1SScott Long 	struct resource	*irqres;
3641f1c579b1SScott Long 	int	rid;
3642f1c579b1SScott Long 
3643ad6d6297SScott Long 	if(acb == NULL) {
3644ad6d6297SScott Long 		printf("arcmsr%d: cannot allocate softc\n", unit);
3645ad6d6297SScott Long 		return (ENOMEM);
3646ad6d6297SScott Long 	}
36475878cbecSScott Long 	ARCMSR_LOCK_INIT(&acb->qbuffer_lock, "arcmsr Q buffer lock");
3648ad6d6297SScott Long 	if(arcmsr_initialize(dev)) {
3649ad6d6297SScott Long 		printf("arcmsr%d: initialize failure!\n", unit);
36505878cbecSScott Long 		ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock);
3651f1c579b1SScott Long 		return ENXIO;
3652f1c579b1SScott Long 	}
3653f1c579b1SScott Long 	/* After setting up the adapter, map our interrupt */
3654f1c579b1SScott Long 	rid=0;
3655ad6d6297SScott Long 	irqres=bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0ul, ~0ul, 1, RF_SHAREABLE | RF_ACTIVE);
3656ad6d6297SScott Long 	if(irqres == NULL ||
365744f05562SScott Long #if __FreeBSD_version >= 700025
3658*d74001adSXin LI 		bus_setup_intr(dev, irqres, INTR_TYPE_CAM|INTR_ENTROPY|INTR_MPSAFE, NULL, arcmsr_intr_handler, acb, &acb->ih)) {
365944f05562SScott Long #else
3660*d74001adSXin LI 		bus_setup_intr(dev, irqres, INTR_TYPE_CAM|INTR_ENTROPY|INTR_MPSAFE, arcmsr_intr_handler, acb, &acb->ih)) {
366144f05562SScott Long #endif
3662ad6d6297SScott Long 		arcmsr_free_resource(acb);
36635878cbecSScott Long 		ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock);
3664f1c579b1SScott Long 		printf("arcmsr%d: unable to register interrupt handler!\n", unit);
3665f1c579b1SScott Long 		return ENXIO;
3666f1c579b1SScott Long 	}
3667ad6d6297SScott Long 	acb->irqres=irqres;
3668ad6d6297SScott Long 	acb->pci_dev=dev;
3669ad6d6297SScott Long 	acb->pci_unit=unit;
3670f1c579b1SScott Long 	/*
3671f1c579b1SScott Long 	 * Now let the CAM generic SCSI layer find the SCSI devices on
3672f1c579b1SScott Long 	 * the bus *  start queue to reset to the idle loop. *
3673f1c579b1SScott Long 	 * Create device queue of SIM(s) *  (MAX_START_JOB - 1) :
3674f1c579b1SScott Long 	 * max_sim_transactions
3675f1c579b1SScott Long 	*/
3676f1c579b1SScott Long 	devq=cam_simq_alloc(ARCMSR_MAX_START_JOB);
3677ad6d6297SScott Long 	if(devq == NULL) {
3678ad6d6297SScott Long 	    arcmsr_free_resource(acb);
3679ad6d6297SScott Long 		bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres);
36805878cbecSScott Long 		ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock);
3681ad6d6297SScott Long 		printf("arcmsr%d: cam_simq_alloc failure!\n", unit);
3682f1c579b1SScott Long 		return ENXIO;
3683f1c579b1SScott Long 	}
368444f05562SScott Long #if __FreeBSD_version >= 700025
3685*d74001adSXin LI 	acb->psim=cam_sim_alloc(arcmsr_action, arcmsr_poll, "arcmsr", acb, unit, &acb->qbuffer_lock, 1, ARCMSR_MAX_OUTSTANDING_CMD, devq);
368644f05562SScott Long #else
3687*d74001adSXin LI 	acb->psim=cam_sim_alloc(arcmsr_action, arcmsr_poll, "arcmsr", acb, unit, 1, ARCMSR_MAX_OUTSTANDING_CMD, devq);
368844f05562SScott Long #endif
3689ad6d6297SScott Long 	if(acb->psim == NULL) {
3690ad6d6297SScott Long 		arcmsr_free_resource(acb);
3691ad6d6297SScott Long 		bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres);
3692f1c579b1SScott Long 		cam_simq_free(devq);
36935878cbecSScott Long 		ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock);
3694ad6d6297SScott Long 		printf("arcmsr%d: cam_sim_alloc failure!\n", unit);
3695f1c579b1SScott Long 		return ENXIO;
3696f1c579b1SScott Long 	}
36975878cbecSScott Long 	ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
3698f40b4cabSScott Long #if __FreeBSD_version >= 700044
3699b50569b7SScott Long 	if(xpt_bus_register(acb->psim, dev, 0) != CAM_SUCCESS) {
370044f05562SScott Long #else
370144f05562SScott Long 	if(xpt_bus_register(acb->psim, 0) != CAM_SUCCESS) {
370244f05562SScott Long #endif
3703ad6d6297SScott Long 		arcmsr_free_resource(acb);
3704ad6d6297SScott Long 		bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres);
3705ad6d6297SScott Long 		cam_sim_free(acb->psim, /*free_devq*/TRUE);
37065878cbecSScott Long 		ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock);
3707ad6d6297SScott Long 		printf("arcmsr%d: xpt_bus_register failure!\n", unit);
3708f1c579b1SScott Long 		return ENXIO;
3709f1c579b1SScott Long 	}
3710*d74001adSXin LI 	if(xpt_create_path(&acb->ppath, /* periph */ NULL, cam_sim_path(acb->psim), CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
3711ad6d6297SScott Long 		arcmsr_free_resource(acb);
3712ad6d6297SScott Long 		bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres);
3713ad6d6297SScott Long 		xpt_bus_deregister(cam_sim_path(acb->psim));
3714ad6d6297SScott Long 		cam_sim_free(acb->psim, /* free_simq */ TRUE);
37155878cbecSScott Long 		ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock);
3716ad6d6297SScott Long 		printf("arcmsr%d: xpt_create_path failure!\n", unit);
3717f1c579b1SScott Long 		return ENXIO;
3718f1c579b1SScott Long 	}
3719f1c579b1SScott Long 	/*
3720f1c579b1SScott Long 	****************************************************
3721f1c579b1SScott Long 	*/
3722ad6d6297SScott Long 	xpt_setup_ccb(&csa.ccb_h, acb->ppath, /*priority*/5);
3723f1c579b1SScott Long 	csa.ccb_h.func_code=XPT_SASYNC_CB;
3724f1c579b1SScott Long 	csa.event_enable=AC_FOUND_DEVICE|AC_LOST_DEVICE;
3725f1c579b1SScott Long 	csa.callback=arcmsr_async;
3726ad6d6297SScott Long 	csa.callback_arg=acb->psim;
3727f1c579b1SScott Long 	xpt_action((union ccb *)&csa);
37285878cbecSScott Long 	ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
3729f1c579b1SScott Long 	/* Create the control device.  */
3730*d74001adSXin LI 	acb->ioctl_dev=make_dev(&arcmsr_cdevsw, unit, UID_ROOT, GID_WHEEL /* GID_OPERATOR */, S_IRUSR | S_IWUSR, "arcmsr%d", unit);
3731*d74001adSXin LI 
3732f1c579b1SScott Long #if __FreeBSD_version < 503000
3733ad6d6297SScott Long 	acb->ioctl_dev->si_drv1=acb;
3734f1c579b1SScott Long #endif
3735f1c579b1SScott Long #if __FreeBSD_version > 500005
3736ad6d6297SScott Long 	(void)make_dev_alias(acb->ioctl_dev, "arc%d", unit);
3737f1c579b1SScott Long #endif
3738*d74001adSXin LI #if __FreeBSD_version > 500000
3739*d74001adSXin LI 	callout_init(&acb->devmap_callout, /*mpsafe*/1);
3740*d74001adSXin LI #else
3741*d74001adSXin LI 	callout_init(&acb->devmap_callout);
3742*d74001adSXin LI #endif
3743*d74001adSXin LI 	callout_reset(&acb->devmap_callout, 60 * hz, arcmsr_polling_devmap, acb);
3744f1c579b1SScott Long 	return 0;
3745f1c579b1SScott Long }
3746f1c579b1SScott Long /*
3747f1c579b1SScott Long ************************************************************************
3748f1c579b1SScott Long ************************************************************************
3749f1c579b1SScott Long */
3750f2aa0e9fSWarner Losh static int arcmsr_probe(device_t dev)
3751f1c579b1SScott Long {
3752ad6d6297SScott Long 	u_int32_t id;
3753ad6d6297SScott Long 	static char buf[256];
3754ad6d6297SScott Long 	char *type;
3755ad6d6297SScott Long 	int raid6 = 1;
3756ad6d6297SScott Long 
3757ad6d6297SScott Long 	if (pci_get_vendor(dev) != PCI_VENDOR_ID_ARECA) {
3758ad6d6297SScott Long 		return (ENXIO);
3759ad6d6297SScott Long 	}
3760ad6d6297SScott Long 	switch(id=pci_get_devid(dev)) {
3761f1c579b1SScott Long 	case PCIDevVenIDARC1110:
3762f1c579b1SScott Long 	case PCIDevVenIDARC1210:
376344f05562SScott Long 	case PCIDevVenIDARC1201:
3764ad6d6297SScott Long 		raid6 = 0;
3765ad6d6297SScott Long 		/*FALLTHRU*/
3766ad6d6297SScott Long 	case PCIDevVenIDARC1120:
3767ad6d6297SScott Long 	case PCIDevVenIDARC1130:
3768ad6d6297SScott Long 	case PCIDevVenIDARC1160:
3769ad6d6297SScott Long 	case PCIDevVenIDARC1170:
3770f1c579b1SScott Long 	case PCIDevVenIDARC1220:
3771f1c579b1SScott Long 	case PCIDevVenIDARC1230:
3772f1c579b1SScott Long 	case PCIDevVenIDARC1260:
3773ad6d6297SScott Long 	case PCIDevVenIDARC1270:
3774ad6d6297SScott Long 	case PCIDevVenIDARC1280:
3775ad6d6297SScott Long 		type = "SATA";
3776ad6d6297SScott Long 		break;
3777*d74001adSXin LI 	case PCIDevVenIDARC1212:
3778*d74001adSXin LI 	case PCIDevVenIDARC1222:
3779ad6d6297SScott Long 	case PCIDevVenIDARC1380:
3780ad6d6297SScott Long 	case PCIDevVenIDARC1381:
3781ad6d6297SScott Long 	case PCIDevVenIDARC1680:
3782ad6d6297SScott Long 	case PCIDevVenIDARC1681:
3783*d74001adSXin LI 		type = "SAS 3G";
3784*d74001adSXin LI 		break;
3785*d74001adSXin LI 	case PCIDevVenIDARC1880:
3786*d74001adSXin LI 		type = "SAS 6G";
3787ad6d6297SScott Long 		break;
3788ad6d6297SScott Long 	default:
3789ad6d6297SScott Long 		type = "X-TYPE";
3790ad6d6297SScott Long 		break;
3791f1c579b1SScott Long 	}
3792ad6d6297SScott Long 	sprintf(buf, "Areca %s Host Adapter RAID Controller %s\n", type, raid6 ? "(RAID6 capable)" : "");
3793ad6d6297SScott Long 	device_set_desc_copy(dev, buf);
3794ad6d6297SScott Long 	return 0;
3795f1c579b1SScott Long }
3796f1c579b1SScott Long /*
3797f1c579b1SScott Long ************************************************************************
3798f1c579b1SScott Long ************************************************************************
3799f1c579b1SScott Long */
3800f2aa0e9fSWarner Losh static int arcmsr_shutdown(device_t dev)
3801f1c579b1SScott Long {
380244f05562SScott Long 	u_int32_t  i;
3803ad6d6297SScott Long 	u_int32_t intmask_org;
3804ad6d6297SScott Long 	struct CommandControlBlock *srb;
3805ad6d6297SScott Long 	struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev);
3806f1c579b1SScott Long 
3807f1c579b1SScott Long 	/* stop adapter background rebuild */
38085878cbecSScott Long 	ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
380944f05562SScott Long 	/* disable all outbound interrupt */
381044f05562SScott Long 	intmask_org=arcmsr_disable_allintr(acb);
3811ad6d6297SScott Long 	arcmsr_stop_adapter_bgrb(acb);
3812ad6d6297SScott Long 	arcmsr_flush_adapter_cache(acb);
3813f1c579b1SScott Long 	/* abort all outstanding command */
3814ad6d6297SScott Long 	acb->acb_flags |= ACB_F_SCSISTOPADAPTER;
3815ad6d6297SScott Long 	acb->acb_flags &= ~ACB_F_IOP_INITED;
3816ad6d6297SScott Long 	if(acb->srboutstandingcount!=0) {
381744f05562SScott Long 		/*clear and abort all outbound posted Q*/
381844f05562SScott Long 		arcmsr_done4abort_postqueue(acb);
381944f05562SScott Long 		/* talk to iop 331 outstanding command aborted*/
3820ad6d6297SScott Long 		arcmsr_abort_allcmd(acb);
3821ad6d6297SScott Long 		for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++) {
3822ad6d6297SScott Long 			srb=acb->psrb_pool[i];
3823ad6d6297SScott Long 			if(srb->startdone==ARCMSR_SRB_START) {
3824ad6d6297SScott Long 				srb->startdone=ARCMSR_SRB_ABORTED;
3825ad6d6297SScott Long 				srb->pccb->ccb_h.status |= CAM_REQ_ABORTED;
3826ad6d6297SScott Long 				arcmsr_srb_complete(srb, 1);
3827f1c579b1SScott Long 			}
3828f1c579b1SScott Long 		}
3829f1c579b1SScott Long 	}
3830ad6d6297SScott Long 	atomic_set_int(&acb->srboutstandingcount, 0);
3831ad6d6297SScott Long 	acb->workingsrb_doneindex=0;
3832ad6d6297SScott Long 	acb->workingsrb_startindex=0;
38335878cbecSScott Long 	ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
3834f2aa0e9fSWarner Losh 	return (0);
3835f1c579b1SScott Long }
3836f1c579b1SScott Long /*
3837f1c579b1SScott Long ************************************************************************
3838f1c579b1SScott Long ************************************************************************
3839f1c579b1SScott Long */
3840f2aa0e9fSWarner Losh static int arcmsr_detach(device_t dev)
3841f1c579b1SScott Long {
3842ad6d6297SScott Long 	struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev);
384344f05562SScott Long 	int i;
3844f1c579b1SScott Long 
3845*d74001adSXin LI 	callout_stop(&acb->devmap_callout);
38465878cbecSScott Long 	bus_teardown_intr(dev, acb->irqres, acb->ih);
3847f1c579b1SScott Long 	arcmsr_shutdown(dev);
3848ad6d6297SScott Long 	arcmsr_free_resource(acb);
384944f05562SScott Long 	for(i=0; (acb->sys_res_arcmsr[i]!=NULL) && (i<2); i++) {
385044f05562SScott Long 		bus_release_resource(dev, SYS_RES_MEMORY, PCIR_BAR(i), acb->sys_res_arcmsr[i]);
385144f05562SScott Long 	}
3852ad6d6297SScott Long 	bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres);
38535878cbecSScott Long 	ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
3854ad6d6297SScott Long 	xpt_async(AC_LOST_DEVICE, acb->ppath, NULL);
3855ad6d6297SScott Long 	xpt_free_path(acb->ppath);
3856ad6d6297SScott Long 	xpt_bus_deregister(cam_sim_path(acb->psim));
3857ad6d6297SScott Long 	cam_sim_free(acb->psim, TRUE);
38585878cbecSScott Long 	ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
38595878cbecSScott Long 	ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock);
3860f1c579b1SScott Long 	return (0);
3861f1c579b1SScott Long }
3862f1c579b1SScott Long 
3863f1c579b1SScott Long 
3864