xref: /freebsd/sys/dev/arcmsr/arcmsr.c (revision b50569b71dfb110a58aa3e83f629115291802a74)
1f1c579b1SScott Long /*
246a7789eSMatt Jacob *****************************************************************************************
3f1c579b1SScott Long **        O.S   : FreeBSD
4f1c579b1SScott Long **   FILE NAME  : arcmsr.c
5f1c579b1SScott Long **        BY    : Erich Chen
6f1c579b1SScott Long **   Description: SCSI RAID Device Driver for
7ad6d6297SScott Long **                ARECA (ARC11XX/ARC12XX/ARC13XX/ARC16XX) 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 **
13f1c579b1SScott Long ** Copyright (c) 2004-2006 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
57f48f00a1SScott Long 
58f1c579b1SScott Long ******************************************************************************************
59ad6d6297SScott Long * $FreeBSD$
60f1c579b1SScott Long */
61f1c579b1SScott Long #include <sys/param.h>
62f1c579b1SScott Long #include <sys/systm.h>
63f1c579b1SScott Long #include <sys/malloc.h>
64f1c579b1SScott Long #include <sys/kernel.h>
65f1c579b1SScott Long #include <sys/bus.h>
66f1c579b1SScott Long #include <sys/queue.h>
67f1c579b1SScott Long #include <sys/stat.h>
68f1c579b1SScott Long #include <sys/devicestat.h>
69f1c579b1SScott Long #include <sys/kthread.h>
70f1c579b1SScott Long #include <sys/module.h>
71f1c579b1SScott Long #include <sys/proc.h>
72f1c579b1SScott Long #include <sys/lock.h>
73f1c579b1SScott Long #include <sys/sysctl.h>
74f1c579b1SScott Long #include <sys/poll.h>
75f1c579b1SScott Long #include <sys/ioccom.h>
76f1c579b1SScott Long #include <vm/vm.h>
77f1c579b1SScott Long #include <vm/vm_param.h>
78f1c579b1SScott Long #include <vm/pmap.h>
79f1c579b1SScott Long 
80f1c579b1SScott Long #include <isa/rtc.h>
81f1c579b1SScott Long 
82f1c579b1SScott Long #include <machine/bus.h>
83f1c579b1SScott Long #include <machine/resource.h>
84f1c579b1SScott Long #include <machine/atomic.h>
85f1c579b1SScott Long #include <sys/conf.h>
86f1c579b1SScott Long #include <sys/rman.h>
87f1c579b1SScott Long 
88f1c579b1SScott Long #include <cam/cam.h>
89f1c579b1SScott Long #include <cam/cam_ccb.h>
90f1c579b1SScott Long #include <cam/cam_sim.h>
91f1c579b1SScott Long #include <cam/cam_xpt_sim.h>
92f1c579b1SScott Long #include <cam/cam_debug.h>
93f1c579b1SScott Long #include <cam/scsi/scsi_all.h>
94f1c579b1SScott Long #include <cam/scsi/scsi_message.h>
95f1c579b1SScott Long /*
96f1c579b1SScott Long **************************************************************************
97f1c579b1SScott Long **************************************************************************
98f1c579b1SScott Long */
99f1c579b1SScott Long #if __FreeBSD_version >= 500005
100f1c579b1SScott Long     #include <sys/selinfo.h>
101f1c579b1SScott Long     #include <sys/mutex.h>
102ad6d6297SScott Long     #include <sys/endian.h>
103f1c579b1SScott Long     #include <dev/pci/pcivar.h>
104f1c579b1SScott Long     #include <dev/pci/pcireg.h>
105f1c579b1SScott Long     #define ARCMSR_LOCK_INIT(l, s)	mtx_init(l, s, NULL, MTX_DEF|MTX_RECURSE)
106f1c579b1SScott Long     #define ARCMSR_LOCK_ACQUIRE(l)	mtx_lock(l)
107f1c579b1SScott Long     #define ARCMSR_LOCK_RELEASE(l)	mtx_unlock(l)
108ad6d6297SScott Long     #define ARCMSR_LOCK_TRY(l)		mtx_trylock(l)
109ad6d6297SScott Long     #define arcmsr_htole32(x)		htole32(x)
110f1c579b1SScott Long     typedef struct mtx		arcmsr_lock_t;
111f1c579b1SScott Long #else
112f1c579b1SScott Long     #include <sys/select.h>
113f1c579b1SScott Long     #include <pci/pcivar.h>
114f1c579b1SScott Long     #include <pci/pcireg.h>
115f1c579b1SScott Long     #define ARCMSR_LOCK_INIT(l, s)	simple_lock_init(l)
116f1c579b1SScott Long     #define ARCMSR_LOCK_ACQUIRE(l)	simple_lock(l)
117f1c579b1SScott Long     #define ARCMSR_LOCK_RELEASE(l)	simple_unlock(l)
118ad6d6297SScott Long     #define ARCMSR_LOCK_TRY(l)		simple_lock_try(l)
119ad6d6297SScott Long     #define arcmsr_htole32(x)		(x)
120f1c579b1SScott Long     typedef struct simplelock		arcmsr_lock_t;
121f1c579b1SScott Long #endif
122f1c579b1SScott Long #include <dev/arcmsr/arcmsr.h>
123ad6d6297SScott Long #define ARCMSR_SRBS_POOL_SIZE           ((sizeof(struct CommandControlBlock) * ARCMSR_MAX_FREESRB_NUM)+0x20)
124f1c579b1SScott Long /*
125f1c579b1SScott Long **************************************************************************
126f1c579b1SScott Long **************************************************************************
127f1c579b1SScott Long */
128ad6d6297SScott Long #define CHIP_REG_READ32(r)	bus_space_read_4(acb->btag, acb->bhandle, offsetof(struct MessageUnit,r))
129ad6d6297SScott Long #define CHIP_REG_WRITE32(r,d)	bus_space_write_4(acb->btag, acb->bhandle, offsetof(struct MessageUnit,r), d)
130f1c579b1SScott Long /*
131f1c579b1SScott Long **************************************************************************
132f1c579b1SScott Long **************************************************************************
133f1c579b1SScott Long */
134ad6d6297SScott Long static struct CommandControlBlock * arcmsr_get_freesrb(struct AdapterControlBlock *acb);
135ad6d6297SScott Long static u_int8_t arcmsr_seek_cmd2abort(union ccb * abortccb);
136ad6d6297SScott Long static u_int8_t arcmsr_wait_msgint_ready(struct AdapterControlBlock *acb);
137ad6d6297SScott Long static u_int32_t arcmsr_probe(device_t dev);
138ad6d6297SScott Long static u_int32_t arcmsr_attach(device_t dev);
139ad6d6297SScott Long static u_int32_t arcmsr_detach(device_t dev);
140ad6d6297SScott Long static u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t ioctl_cmd, caddr_t arg);
141ad6d6297SScott Long static void arcmsr_iop_parking(struct AdapterControlBlock *acb);
142ad6d6297SScott Long static void arcmsr_shutdown(device_t dev);
143ad6d6297SScott Long static void arcmsr_interrupt(void *arg);
144ad6d6297SScott Long static void arcmsr_polling_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb);
145ad6d6297SScott Long static void arcmsr_free_resource(struct AdapterControlBlock *acb);
146ad6d6297SScott Long static void arcmsr_bus_reset(struct AdapterControlBlock *acb);
147ad6d6297SScott Long static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb);
148ad6d6297SScott Long static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb);
149ad6d6297SScott Long static void arcmsr_iop_init(struct AdapterControlBlock *acb);
150ad6d6297SScott Long static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb);
151ad6d6297SScott Long static void arcmsr_post_Qbuffer(struct AdapterControlBlock *acb);
152ad6d6297SScott Long static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb);
153ad6d6297SScott Long static void arcmsr_srb_complete(struct CommandControlBlock *srb, int stand_flag);
154ad6d6297SScott Long static void arcmsr_iop_reset(struct AdapterControlBlock *acb);
155ad6d6297SScott Long static void arcmsr_report_sense_info(struct CommandControlBlock *srb);
156ad6d6297SScott Long static void arcmsr_build_srb(struct CommandControlBlock *srb, bus_dma_segment_t * dm_segs, u_int32_t nseg);
157ad6d6297SScott Long static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb * pccb);
158ad6d6297SScott Long static int arcmsr_resume(device_t dev);
159ad6d6297SScott Long static int arcmsr_suspend(device_t dev);
160f1c579b1SScott Long /*
161f1c579b1SScott Long **************************************************************************
162ad6d6297SScott Long **************************************************************************
163ad6d6297SScott Long */
164ad6d6297SScott Long static void UDELAY(u_int32_t us) { DELAY(us); }
165ad6d6297SScott Long /*
166ad6d6297SScott Long **************************************************************************
167f1c579b1SScott Long **************************************************************************
168f1c579b1SScott Long */
169f1c579b1SScott Long static bus_dmamap_callback_t arcmsr_map_freesrb;
170f1c579b1SScott Long static bus_dmamap_callback_t arcmsr_executesrb;
171f1c579b1SScott Long /*
172f1c579b1SScott Long **************************************************************************
173f1c579b1SScott Long **************************************************************************
174f1c579b1SScott Long */
175f1c579b1SScott Long static d_open_t	arcmsr_open;
176f1c579b1SScott Long static d_close_t arcmsr_close;
177f1c579b1SScott Long static d_ioctl_t arcmsr_ioctl;
178f1c579b1SScott Long 
179f1c579b1SScott Long static device_method_t arcmsr_methods[]={
180f1c579b1SScott Long 	DEVMETHOD(device_probe,		arcmsr_probe),
181f1c579b1SScott Long 	DEVMETHOD(device_attach,	arcmsr_attach),
182f1c579b1SScott Long 	DEVMETHOD(device_detach,	arcmsr_detach),
183f1c579b1SScott Long 	DEVMETHOD(device_shutdown,	arcmsr_shutdown),
184ad6d6297SScott Long 	DEVMETHOD(device_suspend,	arcmsr_suspend),
185ad6d6297SScott Long 	DEVMETHOD(device_resume,	arcmsr_resume),
186ad6d6297SScott Long 
187ad6d6297SScott Long 	DEVMETHOD(bus_print_child,	bus_generic_print_child),
188ad6d6297SScott Long 	DEVMETHOD(bus_driver_added, 	bus_generic_driver_added),
189f1c579b1SScott Long 	{ 0, 0 }
190f1c579b1SScott Long };
191f1c579b1SScott Long 
192f1c579b1SScott Long static driver_t arcmsr_driver={
193ad6d6297SScott Long 	"arcmsr", arcmsr_methods, sizeof(struct AdapterControlBlock)
194f1c579b1SScott Long };
195f1c579b1SScott Long 
196f1c579b1SScott Long static devclass_t arcmsr_devclass;
197f1c579b1SScott Long DRIVER_MODULE(arcmsr, pci, arcmsr_driver, arcmsr_devclass, 0, 0);
198d3cf342dSScott Long MODULE_DEPEND(arcmsr, pci, 1, 1, 1);
199d3cf342dSScott Long MODULE_DEPEND(arcmsr, cam, 1, 1, 1);
200ad6d6297SScott Long #ifndef BUS_DMA_COHERENT
201ad6d6297SScott Long 	#define	BUS_DMA_COHERENT	0x04	/* hint: map memory in a coherent way */
202ad6d6297SScott Long #endif
203ad6d6297SScott Long #if __FreeBSD_version >= 501000
204ad6d6297SScott Long 	#ifndef D_NEEDGIANT
205ad6d6297SScott Long 		#define D_NEEDGIANT	0x00400000	/* driver want Giant */
206ad6d6297SScott Long 	#endif
207ad6d6297SScott Long 	#ifndef D_VERSION
208ad6d6297SScott Long 		#define D_VERSION	0x20011966
209ad6d6297SScott Long 	#endif
210f1c579b1SScott Long 	static struct cdevsw arcmsr_cdevsw={
211ad6d6297SScott Long 	#if __FreeBSD_version > 502010
212f1c579b1SScott Long 		.d_version = D_VERSION,
213ad6d6297SScott Long 	#endif
214f1c579b1SScott Long 	.d_flags   = D_NEEDGIANT,
215f1c579b1SScott Long 	.d_open    = arcmsr_open, 		/* open     */
216f1c579b1SScott Long 	.d_close   = arcmsr_close, 		/* close    */
217f1c579b1SScott Long 	.d_ioctl   = arcmsr_ioctl, 		/* ioctl    */
218f1c579b1SScott Long 	.d_name    = "arcmsr", 			/* name     */
219f1c579b1SScott Long 	};
220f1c579b1SScott Long #else
221f1c579b1SScott Long 	#define ARCMSR_CDEV_MAJOR	180
222f1c579b1SScott Long 
223f1c579b1SScott Long 	static struct cdevsw arcmsr_cdevsw = {
224f1c579b1SScott Long 		arcmsr_open, 		        /* open     */
225f1c579b1SScott Long 		arcmsr_close, 		        /* close    */
226f1c579b1SScott Long 		noread, 		        /* read     */
227f1c579b1SScott Long 		nowrite, 		        /* write    */
228f1c579b1SScott Long 		arcmsr_ioctl, 		        /* ioctl    */
229f1c579b1SScott Long 		nopoll, 		        /* poll     */
230f1c579b1SScott Long 		nommap, 		        /* mmap     */
231f1c579b1SScott Long 		nostrategy, 		        /* strategy */
232f1c579b1SScott Long 		"arcmsr", 		        /* name     */
233f1c579b1SScott Long 		ARCMSR_CDEV_MAJOR, 		/* major    */
234f1c579b1SScott Long 		nodump, 			/* dump     */
235f1c579b1SScott Long 		nopsize, 			/* psize    */
236f1c579b1SScott Long 		0				/* flags    */
237f1c579b1SScott Long 	};
238f1c579b1SScott Long #endif
239f1c579b1SScott Long 
240f1c579b1SScott Long #if __FreeBSD_version < 500005
241f1c579b1SScott Long 	static int arcmsr_open(dev_t dev, int flags, int fmt, struct proc *proc)
242f1c579b1SScott Long #else
243f1c579b1SScott Long     #if __FreeBSD_version < 503000
244f1c579b1SScott Long 	static int arcmsr_open(dev_t dev, int flags, int fmt, struct thread *proc)
245f1c579b1SScott Long     #else
246f1c579b1SScott Long 	static int arcmsr_open(struct cdev *dev, int flags, int fmt, d_thread_t *proc)
247f1c579b1SScott Long     #endif
248f1c579b1SScott Long #endif
249f1c579b1SScott Long {
250f1c579b1SScott Long 	#if __FreeBSD_version < 503000
251ad6d6297SScott Long 	    struct AdapterControlBlock *acb=dev->si_drv1;
252f1c579b1SScott Long 	#else
253f1c579b1SScott Long 		int	unit = minor(dev);
254ad6d6297SScott Long 		struct AdapterControlBlock *acb = devclass_get_softc(arcmsr_devclass, unit);
255f1c579b1SScott Long 	#endif
256ad6d6297SScott Long 	if(acb==NULL) {
257f1c579b1SScott Long 		return ENXIO;
258f1c579b1SScott Long 	}
259f1c579b1SScott Long 	return 0;
260f1c579b1SScott Long }
261f1c579b1SScott Long /*
262f1c579b1SScott Long **************************************************************************
263f1c579b1SScott Long **************************************************************************
264f1c579b1SScott Long */
265f1c579b1SScott Long #if __FreeBSD_version < 500005
266f1c579b1SScott Long 	static int arcmsr_close(dev_t dev, int flags, int fmt, struct proc *proc)
267f1c579b1SScott Long #else
268f1c579b1SScott Long     #if __FreeBSD_version < 503000
269f1c579b1SScott Long 	static int arcmsr_close(dev_t dev, int flags, int fmt, struct thread *proc)
270f1c579b1SScott Long     #else
271f1c579b1SScott Long 	static int arcmsr_close(struct cdev *dev, int flags, int fmt, d_thread_t *proc)
272f1c579b1SScott Long     #endif
273f1c579b1SScott Long #endif
274f1c579b1SScott Long {
275f1c579b1SScott Long 	#if __FreeBSD_version < 503000
276ad6d6297SScott Long 		struct AdapterControlBlock *acb=dev->si_drv1;
277f1c579b1SScott Long 	#else
278f1c579b1SScott Long 		int	unit = minor(dev);
279ad6d6297SScott Long 		struct AdapterControlBlock *acb = devclass_get_softc(arcmsr_devclass, unit);
280f1c579b1SScott Long 	#endif
281ad6d6297SScott Long 	if(acb==NULL) {
282f1c579b1SScott Long 		return ENXIO;
283f1c579b1SScott Long 	}
284f1c579b1SScott Long 	return 0;
285f1c579b1SScott Long }
286f1c579b1SScott Long /*
287f1c579b1SScott Long **************************************************************************
288f1c579b1SScott Long **************************************************************************
289f1c579b1SScott Long */
290f1c579b1SScott Long #if __FreeBSD_version < 500005
291f1c579b1SScott Long 	static int arcmsr_ioctl(dev_t dev, u_long ioctl_cmd, caddr_t arg, int flags, struct proc *proc)
292f1c579b1SScott Long #else
293f1c579b1SScott Long     #if __FreeBSD_version < 503000
294f1c579b1SScott Long 	static int arcmsr_ioctl(dev_t dev, u_long ioctl_cmd, caddr_t arg, int flags, struct thread *proc)
295f1c579b1SScott Long     #else
296f1c579b1SScott Long 	static int arcmsr_ioctl(struct cdev *dev, u_long ioctl_cmd, caddr_t arg, int flags, d_thread_t *proc)
297f1c579b1SScott Long     #endif
298f1c579b1SScott Long #endif
299f1c579b1SScott Long {
300f1c579b1SScott Long 	#if __FreeBSD_version < 503000
301ad6d6297SScott Long 		struct AdapterControlBlock *acb=dev->si_drv1;
302f1c579b1SScott Long 	#else
303f1c579b1SScott Long 		int	unit = minor(dev);
304ad6d6297SScott Long 		struct AdapterControlBlock *acb = devclass_get_softc(arcmsr_devclass, unit);
305f1c579b1SScott Long 	#endif
306f1c579b1SScott Long 
307ad6d6297SScott Long 	if(acb==NULL) {
308f1c579b1SScott Long 		return ENXIO;
309f1c579b1SScott Long 	}
310ad6d6297SScott Long 	return(arcmsr_iop_ioctlcmd(acb, ioctl_cmd, arg));
311f1c579b1SScott Long }
312f1c579b1SScott Long /*
313ad6d6297SScott Long *******************************************************************************
314ad6d6297SScott Long *******************************************************************************
315f1c579b1SScott Long */
316ad6d6297SScott Long static int arcmsr_suspend(device_t dev)
317f1c579b1SScott Long {
318ad6d6297SScott Long 	struct AdapterControlBlock	*acb = device_get_softc(dev);
319ad6d6297SScott Long 	u_int32_t intmask_org;
320f1c579b1SScott Long 
321ad6d6297SScott Long 	/* disable all outbound interrupt */
322ad6d6297SScott Long 	intmask_org=CHIP_REG_READ32(outbound_intmask);
323ad6d6297SScott Long 	CHIP_REG_WRITE32(outbound_intmask, (intmask_org|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE));
324ad6d6297SScott Long 	/* flush controller */
325ad6d6297SScott Long 	arcmsr_iop_parking(acb);
326ad6d6297SScott Long 	return(0);
327ad6d6297SScott Long }
328ad6d6297SScott Long /*
329ad6d6297SScott Long *******************************************************************************
330ad6d6297SScott Long *******************************************************************************
331ad6d6297SScott Long */
332ad6d6297SScott Long static int arcmsr_resume(device_t dev)
333ad6d6297SScott Long {
334ad6d6297SScott Long 	struct AdapterControlBlock	*acb = device_get_softc(dev);
335f1c579b1SScott Long 
336ad6d6297SScott Long 	arcmsr_iop_init(acb);
337ad6d6297SScott Long 	return(0);
338f1c579b1SScott Long }
339f1c579b1SScott Long /*
340f1c579b1SScott Long *********************************************************************************
341f1c579b1SScott Long *********************************************************************************
342f1c579b1SScott Long */
343ad6d6297SScott Long static void arcmsr_async(void *cb_arg, u_int32_t code, struct cam_path *path, void *arg)
344f1c579b1SScott Long {
345ad6d6297SScott Long 	struct AdapterControlBlock *acb;
346ad6d6297SScott Long 	u_int8_t target_id, target_lun;
347f1c579b1SScott Long 	struct cam_sim * sim;
348f1c579b1SScott Long 
349f1c579b1SScott Long 	sim=(struct cam_sim *) cb_arg;
350ad6d6297SScott Long 	acb =(struct AdapterControlBlock *) cam_sim_softc(sim);
351ad6d6297SScott Long 	switch (code) {
352f1c579b1SScott Long 	case AC_LOST_DEVICE:
353f1c579b1SScott Long 		target_id=xpt_path_target_id(path);
354f1c579b1SScott Long 		target_lun=xpt_path_lun_id(path);
355ad6d6297SScott Long 		if((target_id > ARCMSR_MAX_TARGETID) || (target_lun > ARCMSR_MAX_TARGETLUN)) {
356f1c579b1SScott Long 			break;
357f1c579b1SScott Long 		}
358ad6d6297SScott Long 		printf("%s:scsi id%d lun%d device lost \n"
359ad6d6297SScott Long 			, device_get_name(acb->pci_dev), target_id, target_lun);
360f1c579b1SScott Long 		break;
361f1c579b1SScott Long 	default:
362f1c579b1SScott Long 		break;
363f1c579b1SScott Long 	}
364f1c579b1SScott Long }
365f1c579b1SScott Long /*
366f1c579b1SScott Long ************************************************************************
367f1c579b1SScott Long ************************************************************************
368f1c579b1SScott Long */
369ad6d6297SScott Long static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb)
370f1c579b1SScott Long {
371ad6d6297SScott Long 	CHIP_REG_WRITE32(inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE);
372ad6d6297SScott Long 	if(arcmsr_wait_msgint_ready(acb)) {
373ad6d6297SScott Long 		printf("arcmsr%d: wait 'flush adapter cache' timeout \n"
374ad6d6297SScott Long 			, acb->pci_unit);
375ad6d6297SScott Long 	}
376f1c579b1SScott Long 	return;
377f1c579b1SScott Long }
378f1c579b1SScott Long /*
379f1c579b1SScott Long **********************************************************************
380f1c579b1SScott Long **********************************************************************
381f1c579b1SScott Long */
382ad6d6297SScott Long static u_int8_t arcmsr_wait_msgint_ready(struct AdapterControlBlock *acb)
383f1c579b1SScott Long {
384ad6d6297SScott Long 	u_int32_t Index;
385ad6d6297SScott Long 	u_int8_t Retries=0x00;
386ad6d6297SScott Long 
387ad6d6297SScott Long 	do {
388ad6d6297SScott Long 		for(Index=0; Index < 100; Index++) {
389ad6d6297SScott Long 			if(CHIP_REG_READ32(outbound_intstatus) & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) {
390ad6d6297SScott Long 				/*clear interrupt*/
391ad6d6297SScott Long 				CHIP_REG_WRITE32(outbound_intstatus, ARCMSR_MU_OUTBOUND_MESSAGE0_INT);
392ad6d6297SScott Long 				return 0x00;
393f1c579b1SScott Long 			}
394f1c579b1SScott Long 			/* one us delay	*/
395ad6d6297SScott Long 			UDELAY(10000);
396ad6d6297SScott Long 		}/*max 1 seconds*/
397ad6d6297SScott Long 	}while(Retries++ < 20);/*max 20 sec*/
398ad6d6297SScott Long 	return 0xff;
399f1c579b1SScott Long }
400f1c579b1SScott Long /*
401f1c579b1SScott Long **********************************************************************
402f1c579b1SScott Long **********************************************************************
403f1c579b1SScott Long */
404ad6d6297SScott Long static void arcmsr_srb_complete(struct CommandControlBlock *srb, int stand_flag)
405f1c579b1SScott Long {
406ad6d6297SScott Long 	struct AdapterControlBlock *acb=srb->acb;
407ad6d6297SScott Long 	union ccb * pccb=srb->pccb;
408f1c579b1SScott Long 
409ad6d6297SScott Long 	if((pccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
410f1c579b1SScott Long 		bus_dmasync_op_t op;
411f1c579b1SScott Long 
412ad6d6297SScott Long 		if((pccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
413f1c579b1SScott Long 			op = BUS_DMASYNC_POSTREAD;
414ad6d6297SScott Long 		} else {
415f1c579b1SScott Long 			op = BUS_DMASYNC_POSTWRITE;
416f1c579b1SScott Long 		}
417ad6d6297SScott Long 		bus_dmamap_sync(acb->dm_segs_dmat, srb->dm_segs_dmamap, op);
418ad6d6297SScott Long 		bus_dmamap_unload(acb->dm_segs_dmat, srb->dm_segs_dmamap);
419f1c579b1SScott Long 	}
420ad6d6297SScott Long 	ARCMSR_LOCK_ACQUIRE(&acb->workingQ_done_lock);
421ad6d6297SScott Long 	if(stand_flag==1) {
422ad6d6297SScott Long 		atomic_subtract_int(&acb->srboutstandingcount, 1);
423dc3a205bSScott Long 		if((acb->acb_flags & ACB_F_CAM_DEV_QFRZN) && (
424dc3a205bSScott Long 		acb->srboutstandingcount < ARCMSR_RELEASE_SIMQ_LEVEL)) {
425dc3a205bSScott Long 			acb->acb_flags &= ~ACB_F_CAM_DEV_QFRZN;
426dc3a205bSScott Long 			pccb->ccb_h.status |= CAM_RELEASE_SIMQ;
427dc3a205bSScott Long 		}
428ad6d6297SScott Long 	}
429ad6d6297SScott Long 	srb->startdone=ARCMSR_SRB_DONE;
430ad6d6297SScott Long 	srb->srb_flags=0;
431ad6d6297SScott Long 	acb->srbworkingQ[acb->workingsrb_doneindex]=srb;
432ad6d6297SScott Long 	acb->workingsrb_doneindex++;
433ad6d6297SScott Long 	acb->workingsrb_doneindex %= ARCMSR_MAX_FREESRB_NUM;
434ad6d6297SScott Long 	ARCMSR_LOCK_RELEASE(&acb->workingQ_done_lock);
435f1c579b1SScott Long 	xpt_done(pccb);
436f1c579b1SScott Long 	return;
437f1c579b1SScott Long }
438f1c579b1SScott Long /*
439f1c579b1SScott Long **********************************************************************
440f1c579b1SScott Long **********************************************************************
441f1c579b1SScott Long */
442ad6d6297SScott Long static void arcmsr_report_sense_info(struct CommandControlBlock *srb)
443f1c579b1SScott Long {
444ad6d6297SScott Long 	union ccb * pccb=srb->pccb;
445f1c579b1SScott Long 
446ad6d6297SScott Long 	pccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
447ad6d6297SScott Long 	pccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
448ad6d6297SScott Long 	if(&pccb->csio.sense_data) {
449ad6d6297SScott Long 		memset(&pccb->csio.sense_data, 0, sizeof(pccb->csio.sense_data));
450ad6d6297SScott Long 		memcpy(&pccb->csio.sense_data, srb->arcmsr_cdb.SenseData,
451ad6d6297SScott Long 		get_min(sizeof(struct SENSE_DATA), sizeof(pccb->csio.sense_data)));
452ad6d6297SScott Long 		((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70); /* Valid,ErrorCode */
453f1c579b1SScott Long 		pccb->ccb_h.status |= CAM_AUTOSNS_VALID;
454f1c579b1SScott Long 	}
455f1c579b1SScott Long 	return;
456f1c579b1SScott Long }
457f1c579b1SScott Long /*
458f1c579b1SScott Long *********************************************************************
459f1c579b1SScott Long **
460f1c579b1SScott Long *********************************************************************
461f1c579b1SScott Long */
462ad6d6297SScott Long static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb)
463f1c579b1SScott Long {
464ad6d6297SScott Long 	CHIP_REG_WRITE32(inbound_msgaddr0, ARCMSR_INBOUND_MESG0_ABORT_CMD);
465ad6d6297SScott Long 	if(arcmsr_wait_msgint_ready(acb)) {
466ad6d6297SScott Long 		printf("arcmsr%d: wait 'abort all outstanding command' timeout \n"
467ad6d6297SScott Long 			, acb->pci_unit);
468ad6d6297SScott Long 	}
469f1c579b1SScott Long 	return;
470f1c579b1SScott Long }
471f1c579b1SScott Long /*
472f1c579b1SScott Long ****************************************************************************
473f1c579b1SScott Long ****************************************************************************
474f1c579b1SScott Long */
475ad6d6297SScott Long static void arcmsr_iop_reset(struct AdapterControlBlock *acb)
476f1c579b1SScott Long {
477ad6d6297SScott Long 	struct CommandControlBlock *srb;
478ad6d6297SScott Long 	u_int32_t intmask_org, mask;
479ad6d6297SScott Long 	u_int32_t i=0;
480f1c579b1SScott Long 
481ad6d6297SScott Long 	if(acb->srboutstandingcount!=0)
482f1c579b1SScott Long 	{
483f1c579b1SScott Long 		/* talk to iop 331 outstanding command aborted*/
484ad6d6297SScott Long 		arcmsr_abort_allcmd(acb);
485ad6d6297SScott Long 		UDELAY(3000*1000);/*wait for 3 sec for all command aborted*/
486ad6d6297SScott Long 		/* disable all outbound interrupt */
487ad6d6297SScott Long 		intmask_org=CHIP_REG_READ32(outbound_intmask);
488ad6d6297SScott Long 		CHIP_REG_WRITE32(outbound_intmask
489ad6d6297SScott Long 			, intmask_org|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE);
490f1c579b1SScott Long 		/*clear all outbound posted Q*/
491ad6d6297SScott Long 		for(i=0;i<ARCMSR_MAX_OUTSTANDING_CMD;i++) {
492ad6d6297SScott Long 			CHIP_REG_READ32(outbound_queueport);
493f1c579b1SScott Long 		}
494ad6d6297SScott Long 		for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++) {
495ad6d6297SScott Long 			srb=acb->psrb_pool[i];
496ad6d6297SScott Long 			if(srb->startdone==ARCMSR_SRB_START) {
497ad6d6297SScott Long 				srb->startdone=ARCMSR_SRB_ABORTED;
498ad6d6297SScott Long 				srb->pccb->ccb_h.status |= CAM_REQ_ABORTED;
499ad6d6297SScott Long 				arcmsr_srb_complete(srb, 1);
500f1c579b1SScott Long 			}
501f1c579b1SScott Long 		}
502f1c579b1SScott Long 		/* enable all outbound interrupt */
503ad6d6297SScott Long 		mask=~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE
504ad6d6297SScott Long 			|ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE);
505ad6d6297SScott Long 		CHIP_REG_WRITE32(outbound_intmask, intmask_org & mask);
506f1c579b1SScott Long 		/* post abort all outstanding command message to RAID controller */
507f1c579b1SScott Long 	}
508ad6d6297SScott Long 	atomic_set_int(&acb->srboutstandingcount, 0);
509ad6d6297SScott Long 	acb->workingsrb_doneindex=0;
510ad6d6297SScott Long 	acb->workingsrb_startindex=0;
511f1c579b1SScott Long 	return;
512f1c579b1SScott Long }
513f1c579b1SScott Long /*
514f1c579b1SScott Long **********************************************************************
515f1c579b1SScott Long **********************************************************************
516f1c579b1SScott Long */
517ad6d6297SScott Long static void arcmsr_build_srb(struct CommandControlBlock *srb, bus_dma_segment_t *dm_segs, u_int32_t nseg)
518f1c579b1SScott Long {
519ad6d6297SScott Long 	struct ARCMSR_CDB * arcmsr_cdb= &srb->arcmsr_cdb;
520ad6d6297SScott Long 	u_int8_t * psge=(u_int8_t *)&arcmsr_cdb->u;
521ad6d6297SScott Long 	u_int32_t address_lo, address_hi;
522ad6d6297SScott Long 	union ccb * pccb=srb->pccb;
523f1c579b1SScott Long 	struct ccb_scsiio * pcsio= &pccb->csio;
524ad6d6297SScott Long 	u_int32_t arccdbsize=0x30;
525f1c579b1SScott Long 
526ad6d6297SScott Long 	memset(arcmsr_cdb, 0, sizeof(struct ARCMSR_CDB));
527ad6d6297SScott Long 	arcmsr_cdb->Bus=0;
528ad6d6297SScott Long 	arcmsr_cdb->TargetID=pccb->ccb_h.target_id;
529ad6d6297SScott Long 	arcmsr_cdb->LUN=pccb->ccb_h.target_lun;
530ad6d6297SScott Long 	arcmsr_cdb->Function=1;
531ad6d6297SScott Long 	arcmsr_cdb->CdbLength=(u_int8_t)pcsio->cdb_len;
532ad6d6297SScott Long 	arcmsr_cdb->Context=(unsigned long)arcmsr_cdb;
533ad6d6297SScott Long 	bcopy(pcsio->cdb_io.cdb_bytes, arcmsr_cdb->Cdb, pcsio->cdb_len);
534ad6d6297SScott Long 	if(nseg != 0) {
535ad6d6297SScott Long 		struct AdapterControlBlock *acb=srb->acb;
536f1c579b1SScott Long 		bus_dmasync_op_t op;
537ad6d6297SScott Long 		u_int32_t length, i, cdb_sgcount=0;
538f1c579b1SScott Long 
539ad6d6297SScott Long 		if((pccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
540ad6d6297SScott Long 			op=BUS_DMASYNC_PREREAD;
541ad6d6297SScott Long 		} else {
542ad6d6297SScott Long 			op=BUS_DMASYNC_PREWRITE;
543ad6d6297SScott Long 			arcmsr_cdb->Flags|=ARCMSR_CDB_FLAG_WRITE;
544ad6d6297SScott Long 			srb->srb_flags|=SRB_FLAG_WRITE;
545ad6d6297SScott Long 		}
546ad6d6297SScott Long 		bus_dmamap_sync(acb->dm_segs_dmat, srb->dm_segs_dmamap, op);
547ad6d6297SScott Long 		for(i=0;i<nseg;i++) {
548f1c579b1SScott Long 			/* Get the physical address of the current data pointer */
549ad6d6297SScott Long 			length=arcmsr_htole32(dm_segs[i].ds_len);
550ad6d6297SScott Long 			address_lo=arcmsr_htole32(dma_addr_lo32(dm_segs[i].ds_addr));
551ad6d6297SScott Long 			address_hi=arcmsr_htole32(dma_addr_hi32(dm_segs[i].ds_addr));
552ad6d6297SScott Long 			if(address_hi==0) {
553ad6d6297SScott Long 				struct SG32ENTRY * pdma_sg=(struct SG32ENTRY *)psge;
554f1c579b1SScott Long 				pdma_sg->address=address_lo;
555f1c579b1SScott Long 				pdma_sg->length=length;
556ad6d6297SScott Long 				psge += sizeof(struct SG32ENTRY);
557ad6d6297SScott Long 				arccdbsize += sizeof(struct SG32ENTRY);
558ad6d6297SScott Long 			} else {
559ad6d6297SScott Long 				u_int32_t sg64s_size=0, tmplength=length;
560f1c579b1SScott Long 
561ad6d6297SScott Long 				while(1) {
562ad6d6297SScott Long 					u_int64_t span4G, length0;
563ad6d6297SScott Long 					struct SG64ENTRY * pdma_sg=(struct SG64ENTRY *)psge;
564f1c579b1SScott Long 
565ad6d6297SScott Long 					span4G=(u_int64_t)address_lo + tmplength;
566f1c579b1SScott Long 					pdma_sg->addresshigh=address_hi;
567f1c579b1SScott Long 					pdma_sg->address=address_lo;
568ad6d6297SScott Long 					if(span4G > 0x100000000) {
569f1c579b1SScott Long 						/*see if cross 4G boundary*/
570f1c579b1SScott Long 						length0=0x100000000-address_lo;
571ad6d6297SScott Long 						pdma_sg->length=(u_int32_t)length0|IS_SG64_ADDR;
572f1c579b1SScott Long 						address_hi=address_hi+1;
573f1c579b1SScott Long 						address_lo=0;
574ad6d6297SScott Long 						tmplength=tmplength-(u_int32_t)length0;
575ad6d6297SScott Long 						sg64s_size += sizeof(struct SG64ENTRY);
576ad6d6297SScott Long 						psge += sizeof(struct SG64ENTRY);
577f1c579b1SScott Long 						cdb_sgcount++;
578ad6d6297SScott Long 					} else {
579f1c579b1SScott Long     						pdma_sg->length=tmplength|IS_SG64_ADDR;
580ad6d6297SScott Long 						sg64s_size += sizeof(struct SG64ENTRY);
581ad6d6297SScott Long 						psge += sizeof(struct SG64ENTRY);
582f1c579b1SScott Long 						break;
583f1c579b1SScott Long 					}
584f1c579b1SScott Long 				}
585f1c579b1SScott Long 				arccdbsize += sg64s_size;
586f1c579b1SScott Long 			}
587f1c579b1SScott Long 			cdb_sgcount++;
588f1c579b1SScott Long 		}
589ad6d6297SScott Long 		arcmsr_cdb->sgcount=(u_int8_t)cdb_sgcount;
590ad6d6297SScott Long 		arcmsr_cdb->DataLength=pcsio->dxfer_len;
591ad6d6297SScott Long 		if( arccdbsize > 256) {
592ad6d6297SScott Long 			arcmsr_cdb->Flags|=ARCMSR_CDB_FLAG_SGL_BSIZE;
593f1c579b1SScott Long 		}
594f1c579b1SScott Long 	}
595f1c579b1SScott Long     return;
596f1c579b1SScott Long }
597f1c579b1SScott Long /*
598f1c579b1SScott Long **************************************************************************
599f1c579b1SScott Long **************************************************************************
600f1c579b1SScott Long */
601ad6d6297SScott Long static void arcmsr_post_srb(struct AdapterControlBlock *acb, struct CommandControlBlock *srb)
602f1c579b1SScott Long {
603ad6d6297SScott Long 	u_int32_t cdb_shifted_phyaddr=(u_int32_t) srb->cdb_shifted_phyaddr;
604ad6d6297SScott Long 	struct ARCMSR_CDB * arcmsr_cdb=(struct ARCMSR_CDB *)&srb->arcmsr_cdb;
605f1c579b1SScott Long 
606ad6d6297SScott Long 	bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap,
607ad6d6297SScott Long 	(srb->srb_flags & SRB_FLAG_WRITE) ? BUS_DMASYNC_POSTWRITE:BUS_DMASYNC_POSTREAD);
608ad6d6297SScott Long 	atomic_add_int(&acb->srboutstandingcount, 1);
609ad6d6297SScott Long 	srb->startdone=ARCMSR_SRB_START;
610ad6d6297SScott Long 	if(arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) {
611ad6d6297SScott Long 	    CHIP_REG_WRITE32(inbound_queueport, cdb_shifted_phyaddr|ARCMSR_SRBPOST_FLAG_SGL_BSIZE);
612ad6d6297SScott Long 	} else {
613ad6d6297SScott Long 	    CHIP_REG_WRITE32(inbound_queueport, cdb_shifted_phyaddr);
614f1c579b1SScott Long 	}
615f1c579b1SScott Long 	return;
616f1c579b1SScott Long }
617f1c579b1SScott Long /*
618f1c579b1SScott Long **********************************************************************
619f1c579b1SScott Long **********************************************************************
620f1c579b1SScott Long */
621ad6d6297SScott Long static void arcmsr_post_Qbuffer(struct AdapterControlBlock *acb)
622f1c579b1SScott Long {
623ad6d6297SScott Long 	u_int8_t * pQbuffer;
624ad6d6297SScott Long 	struct QBUFFER * pwbuffer=(struct QBUFFER *)&acb->pmu->message_wbuffer;
625ad6d6297SScott Long 	u_int8_t * iop_data=(u_int8_t *)pwbuffer->data;
626ad6d6297SScott Long 	u_int32_t allxfer_len=0;
627f1c579b1SScott Long 
628ad6d6297SScott Long 	if(acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_READED) {
629ad6d6297SScott Long 		acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READED);
630ad6d6297SScott Long 		while((acb->wqbuf_firstindex!=acb->wqbuf_lastindex) && (allxfer_len<124)) {
631ad6d6297SScott Long 			pQbuffer= &acb->wqbuffer[acb->wqbuf_firstindex];
632f1c579b1SScott Long 			memcpy(iop_data, pQbuffer, 1);
633ad6d6297SScott Long 			acb->wqbuf_firstindex++;
634ad6d6297SScott Long 			acb->wqbuf_firstindex %= ARCMSR_MAX_QBUFFER;
635ad6d6297SScott Long 			/*if last index number set it to 0 */
636f1c579b1SScott Long 			iop_data++;
637f1c579b1SScott Long 			allxfer_len++;
638f1c579b1SScott Long 		}
639f1c579b1SScott Long 		pwbuffer->data_len=allxfer_len;
640f1c579b1SScott Long 		/*
641f1c579b1SScott Long 		** push inbound doorbell and wait reply at hwinterrupt routine for next Qbuffer post
642f1c579b1SScott Long 		*/
643ad6d6297SScott Long 		CHIP_REG_WRITE32(inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK);
644ad6d6297SScott Long 	}
645f1c579b1SScott Long 	return;
646f1c579b1SScott Long }
647f1c579b1SScott Long /*
648f1c579b1SScott Long ************************************************************************
649f1c579b1SScott Long ************************************************************************
650f1c579b1SScott Long */
651ad6d6297SScott Long static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb)
652f1c579b1SScott Long {
653ad6d6297SScott Long 	acb->acb_flags &= ~ACB_F_MSG_START_BGRB;
654ad6d6297SScott Long 	CHIP_REG_WRITE32(inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB);
655ad6d6297SScott Long 	if(arcmsr_wait_msgint_ready(acb)) {
656ad6d6297SScott Long 		printf("arcmsr%d: wait 'stop adapter rebulid' timeout \n"
657ad6d6297SScott Long 			, acb->pci_unit);
658ad6d6297SScott Long 	}
659f1c579b1SScott Long 	return;
660f1c579b1SScott Long }
661f1c579b1SScott Long /*
662f1c579b1SScott Long ************************************************************************
663f1c579b1SScott Long ************************************************************************
664f1c579b1SScott Long */
665ad6d6297SScott Long static void arcmsr_poll(struct cam_sim * psim)
666f1c579b1SScott Long {
667f1c579b1SScott Long 	arcmsr_interrupt(cam_sim_softc(psim));
668f1c579b1SScott Long 	return;
669f1c579b1SScott Long }
670f1c579b1SScott Long /*
671f1c579b1SScott Long **********************************************************************
672f1c579b1SScott Long **********************************************************************
673f1c579b1SScott Long */
674ad6d6297SScott Long static void arcmsr_interrupt(void *arg)
675f1c579b1SScott Long {
676ad6d6297SScott Long 	struct AdapterControlBlock *acb=(struct AdapterControlBlock *)arg;
677ad6d6297SScott Long 	struct CommandControlBlock *srb;
678ad6d6297SScott Long 	u_int32_t flag_srb, outbound_intstatus, outbound_doorbell;
679f1c579b1SScott Long 
680f1c579b1SScott Long 	/*
681f1c579b1SScott Long 	*********************************************
682ad6d6297SScott Long 	**   check outbound intstatus
683f1c579b1SScott Long 	*********************************************
684f1c579b1SScott Long 	*/
685ad6d6297SScott Long 	outbound_intstatus=CHIP_REG_READ32(outbound_intstatus) & acb->outbound_int_enable;
686ad6d6297SScott Long 	CHIP_REG_WRITE32(outbound_intstatus, outbound_intstatus);/*clear interrupt*/
687ad6d6297SScott Long 	if(outbound_intstatus & ARCMSR_MU_OUTBOUND_DOORBELL_INT) {
688f1c579b1SScott Long 		/*
689f1c579b1SScott Long 		*********************************************
690ad6d6297SScott Long 		**  DOORBELL
691f1c579b1SScott Long 		*********************************************
692f1c579b1SScott Long 		*/
693ad6d6297SScott Long 		outbound_doorbell=CHIP_REG_READ32(outbound_doorbell);
694ad6d6297SScott Long 		CHIP_REG_WRITE32(outbound_doorbell, outbound_doorbell);/*clear interrupt */
695ad6d6297SScott Long 		if(outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_WRITE_OK) {
696ad6d6297SScott Long 			struct QBUFFER * prbuffer=(struct QBUFFER *)&acb->pmu->message_rbuffer;
697ad6d6297SScott Long 			u_int8_t * iop_data=(u_int8_t *)prbuffer->data;
698ad6d6297SScott Long 			u_int8_t * pQbuffer;
699ad6d6297SScott Long 			u_int32_t my_empty_len, iop_len, rqbuf_firstindex, rqbuf_lastindex;
700ad6d6297SScott Long 
701f1c579b1SScott Long 			/*check this iop data if overflow my rqbuffer*/
702ad6d6297SScott Long 			rqbuf_lastindex=acb->rqbuf_lastindex;
703ad6d6297SScott Long 			rqbuf_firstindex=acb->rqbuf_firstindex;
704f1c579b1SScott Long 			iop_len=prbuffer->data_len;
705f1c579b1SScott Long 			my_empty_len=(rqbuf_firstindex-rqbuf_lastindex-1)&(ARCMSR_MAX_QBUFFER-1);
706ad6d6297SScott Long 			if(my_empty_len>=iop_len) {
707ad6d6297SScott Long 				while(iop_len > 0) {
708ad6d6297SScott Long 					pQbuffer= &acb->rqbuffer[acb->rqbuf_lastindex];
709f1c579b1SScott Long 					memcpy(pQbuffer, iop_data, 1);
710ad6d6297SScott Long 					acb->rqbuf_lastindex++;
711ad6d6297SScott Long 					acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER;
712ad6d6297SScott Long 					/*if last index number set it to 0 */
713f1c579b1SScott Long 					iop_data++;
714f1c579b1SScott Long 					iop_len--;
715f1c579b1SScott Long 				}
716ad6d6297SScott Long 				CHIP_REG_WRITE32(inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK);
717ad6d6297SScott Long 				/*signature, let IOP331 know data has been readed */
718ad6d6297SScott Long 			} else {
719ad6d6297SScott Long 				acb->acb_flags|=ACB_F_IOPDATA_OVERFLOW;
720f1c579b1SScott Long 			}
721f1c579b1SScott Long 		}
722ad6d6297SScott Long 		if(outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_READ_OK) {
723ad6d6297SScott Long 			acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_READED;
724f1c579b1SScott Long 			/*
725f1c579b1SScott Long 			*********************************************
726f1c579b1SScott Long 			*********************************************
727f1c579b1SScott Long 			*/
728ad6d6297SScott Long 			if(acb->wqbuf_firstindex!=acb->wqbuf_lastindex) {
729ad6d6297SScott Long 				u_int8_t * pQbuffer;
730ad6d6297SScott Long 				struct QBUFFER * pwbuffer=(struct QBUFFER *)&acb->pmu->message_wbuffer;
731ad6d6297SScott Long 				u_int8_t * iop_data=(u_int8_t *)pwbuffer->data;
732ad6d6297SScott Long 				u_int32_t allxfer_len=0;
733f1c579b1SScott Long 
734ad6d6297SScott Long 				acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READED);
735ad6d6297SScott Long 				while((acb->wqbuf_firstindex!=acb->wqbuf_lastindex) && (allxfer_len<124)) {
736ad6d6297SScott Long 					pQbuffer= &acb->wqbuffer[acb->wqbuf_firstindex];
737f1c579b1SScott Long    					memcpy(iop_data, pQbuffer, 1);
738ad6d6297SScott Long 					acb->wqbuf_firstindex++;
739ad6d6297SScott Long 					acb->wqbuf_firstindex %= ARCMSR_MAX_QBUFFER;
740ad6d6297SScott Long 					/*if last index number set it to 0 */
741f1c579b1SScott Long 					iop_data++;
742f1c579b1SScott Long 					allxfer_len++;
743f1c579b1SScott Long 				}
744f1c579b1SScott Long 				pwbuffer->data_len=allxfer_len;
745f1c579b1SScott Long 				/*
746ad6d6297SScott Long 				** push inbound doorbell tell iop driver data write ok
747ad6d6297SScott Long 				** and wait reply on next hwinterrupt for next Qbuffer post
748f1c579b1SScott Long 				*/
749ad6d6297SScott Long 				CHIP_REG_WRITE32(inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK);
750f1c579b1SScott Long  			}
751ad6d6297SScott Long 			if(acb->wqbuf_firstindex==acb->wqbuf_lastindex) {
752ad6d6297SScott Long 				acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_CLEARED;
753f1c579b1SScott Long 			}
754f1c579b1SScott Long 		}
755ad6d6297SScott Long 	}
756ad6d6297SScott Long 	if(outbound_intstatus & ARCMSR_MU_OUTBOUND_POSTQUEUE_INT) {
757ad6d6297SScott Long 		int target, lun;
758f1c579b1SScott Long  		/*
759f1c579b1SScott Long 		*****************************************************************************
760f1c579b1SScott Long 		**               areca cdb command done
761f1c579b1SScott Long 		*****************************************************************************
762f1c579b1SScott Long 		*/
763ad6d6297SScott Long 		bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
764ad6d6297SScott Long 		while(1) {
765ad6d6297SScott Long 			if((flag_srb=CHIP_REG_READ32(outbound_queueport)) == 0xFFFFFFFF) {
766f1c579b1SScott Long 				break;/*chip FIFO no srb for completion already*/
767f1c579b1SScott Long 			}
768f1c579b1SScott Long 			/* check if command done with no error*/
769ad6d6297SScott Long 			srb=(struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb << 5));
770ad6d6297SScott Long 			/*frame must be 32 bytes aligned*/
771ad6d6297SScott Long 			if((srb->acb!=acb) || (srb->startdone!=ARCMSR_SRB_START)) {
772ad6d6297SScott Long 				if(srb->startdone==ARCMSR_SRB_ABORTED) {
773ad6d6297SScott Long 					printf("arcmsr%d: srb='%p' isr got aborted command \n"
774ad6d6297SScott Long 						, acb->pci_unit, srb);
775ad6d6297SScott Long 					srb->pccb->ccb_h.status |= CAM_REQ_ABORTED;
776ad6d6297SScott Long 					arcmsr_srb_complete(srb, 1);
777ad6d6297SScott Long 					continue;
778f1c579b1SScott Long 				}
779ad6d6297SScott Long 				printf("arcmsr%d: isr get an illegal srb command done"
780ad6d6297SScott Long 					"acb='%p' srb='%p' srbacb='%p' startdone=0x%x"
781ad6d6297SScott Long 					"srboutstandingcount=%d \n",
782ad6d6297SScott Long 					acb->pci_unit, acb, srb, srb->acb,
783ad6d6297SScott Long 					srb->startdone, acb->srboutstandingcount);
784ad6d6297SScott Long 				continue;
785f1c579b1SScott Long 			}
786ad6d6297SScott Long 			target=srb->pccb->ccb_h.target_id;
787ad6d6297SScott Long 			lun=srb->pccb->ccb_h.target_lun;
788ad6d6297SScott Long 			if((flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR)==0) {
789ad6d6297SScott Long 				if(acb->devstate[target][lun]==ARECA_RAID_GONE) {
790ad6d6297SScott Long 					acb->devstate[target][lun]=ARECA_RAID_GOOD;
791f1c579b1SScott Long 				}
792ad6d6297SScott Long 				srb->pccb->ccb_h.status |= CAM_REQ_CMP;
793ad6d6297SScott Long 				arcmsr_srb_complete(srb, 1);
794ad6d6297SScott Long 			} else {
795ad6d6297SScott Long 				switch(srb->arcmsr_cdb.DeviceStatus) {
796ad6d6297SScott Long 				case ARCMSR_DEV_SELECT_TIMEOUT: {
797ad6d6297SScott Long 						acb->devstate[target][lun]=ARECA_RAID_GONE;
798ad6d6297SScott Long  						srb->pccb->ccb_h.status |= CAM_SEL_TIMEOUT;
799ad6d6297SScott Long 						arcmsr_srb_complete(srb, 1);
800f1c579b1SScott Long 					}
801f1c579b1SScott Long 					break;
802f1c579b1SScott Long 				case ARCMSR_DEV_ABORTED:
803ad6d6297SScott Long 				case ARCMSR_DEV_INIT_FAIL: {
804ad6d6297SScott Long 						acb->devstate[target][lun]=ARECA_RAID_GONE;
805ad6d6297SScott Long  						srb->pccb->ccb_h.status |= CAM_DEV_NOT_THERE;
806ad6d6297SScott Long 						arcmsr_srb_complete(srb, 1);
807f1c579b1SScott Long 					}
808f1c579b1SScott Long 					break;
809ad6d6297SScott Long 				case SCSISTAT_CHECK_CONDITION: {
810ad6d6297SScott Long 						acb->devstate[target][lun]=ARECA_RAID_GOOD;
811ad6d6297SScott Long 						arcmsr_report_sense_info(srb);
812ad6d6297SScott Long 						arcmsr_srb_complete(srb, 1);
813f1c579b1SScott Long 					}
814f1c579b1SScott Long 					break;
815f1c579b1SScott Long 				default:
816ad6d6297SScott Long 					printf("arcmsr%d: scsi id=%d lun=%d"
817ad6d6297SScott Long 						"isr get command error done,"
818ad6d6297SScott Long 						"but got unknow DeviceStatus=0x%x \n"
819ad6d6297SScott Long 						, acb->pci_unit, target, lun
820ad6d6297SScott Long 						,srb->arcmsr_cdb.DeviceStatus);
821ad6d6297SScott Long 					acb->devstate[target][lun]=ARECA_RAID_GONE;
822ad6d6297SScott Long 					srb->pccb->ccb_h.status |= CAM_UNCOR_PARITY;
823ad6d6297SScott Long 					/*unknow error or crc error just for retry*/
824ad6d6297SScott Long 					arcmsr_srb_complete(srb, 1);
825f1c579b1SScott Long 					break;
826f1c579b1SScott Long 				}
827f1c579b1SScott Long 			}
828f1c579b1SScott Long 		}	/*drain reply FIFO*/
829f1c579b1SScott Long 	}
830f1c579b1SScott Long  	return;
831f1c579b1SScott Long }
832f1c579b1SScott Long /*
833ad6d6297SScott Long *******************************************************************************
834ad6d6297SScott Long **
835ad6d6297SScott Long *******************************************************************************
836ad6d6297SScott Long */
837ad6d6297SScott Long static void arcmsr_iop_parking(struct AdapterControlBlock *acb)
838ad6d6297SScott Long {
839ad6d6297SScott Long 	if(acb!=NULL) {
840ad6d6297SScott Long 		/* stop adapter background rebuild */
841ad6d6297SScott Long 		if(acb->acb_flags & ACB_F_MSG_START_BGRB) {
842ad6d6297SScott Long 			arcmsr_stop_adapter_bgrb(acb);
843ad6d6297SScott Long 			arcmsr_flush_adapter_cache(acb);
844ad6d6297SScott Long 		}
845ad6d6297SScott Long 	}
846ad6d6297SScott Long }
847ad6d6297SScott Long /*
848f1c579b1SScott Long ***********************************************************************
849f1c579b1SScott Long **
850f1c579b1SScott Long ************************************************************************
851f1c579b1SScott Long */
852ad6d6297SScott Long u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t ioctl_cmd, caddr_t arg)
853f1c579b1SScott Long {
854ad6d6297SScott Long 	struct CMD_MESSAGE_FIELD * pcmdmessagefld;
855ad6d6297SScott Long 	u_int32_t retvalue=EINVAL;
856f1c579b1SScott Long 
857ad6d6297SScott Long 	pcmdmessagefld=(struct CMD_MESSAGE_FIELD *) arg;
858ad6d6297SScott Long 	if(memcmp(pcmdmessagefld->cmdmessage.Signature, "ARCMSR", 6)!=0) {
859ad6d6297SScott Long 		return retvalue;
860f1c579b1SScott Long 	}
861ad6d6297SScott Long 	ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
862ad6d6297SScott Long 	switch(ioctl_cmd) {
863ad6d6297SScott Long 	case ARCMSR_MESSAGE_READ_RQBUFFER: {
864ad6d6297SScott Long 			u_int8_t * pQbuffer;
865ad6d6297SScott Long 			u_int8_t * ptmpQbuffer=pcmdmessagefld->messagedatabuffer;
866ad6d6297SScott Long 			u_int32_t allxfer_len=0;
867f1c579b1SScott Long 
868ad6d6297SScott Long 			while((acb->rqbuf_firstindex!=acb->rqbuf_lastindex) && (allxfer_len<1031)) {
869f1c579b1SScott Long 				/*copy READ QBUFFER to srb*/
870ad6d6297SScott Long 				pQbuffer= &acb->rqbuffer[acb->rqbuf_firstindex];
871f1c579b1SScott Long 				memcpy(ptmpQbuffer, pQbuffer, 1);
872ad6d6297SScott Long 				acb->rqbuf_firstindex++;
873ad6d6297SScott Long 				acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER;
874ad6d6297SScott Long 				/*if last index number set it to 0 */
875f1c579b1SScott Long 				ptmpQbuffer++;
876f1c579b1SScott Long 				allxfer_len++;
877f1c579b1SScott Long 			}
878ad6d6297SScott Long 			if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
879ad6d6297SScott Long 				struct QBUFFER * prbuffer=(struct QBUFFER *)&acb->pmu->message_rbuffer;
880ad6d6297SScott Long 				u_int8_t * iop_data=(u_int8_t *)prbuffer->data;
881ad6d6297SScott Long 				u_int32_t iop_len;
882f1c579b1SScott Long 
883ad6d6297SScott Long 				acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
884ad6d6297SScott Long 				iop_len=(u_int32_t)prbuffer->data_len;
885f1c579b1SScott Long 				/*this iop data does no chance to make me overflow again here, so just do it*/
886ad6d6297SScott Long 				while(iop_len>0) {
887ad6d6297SScott Long 					pQbuffer= &acb->rqbuffer[acb->rqbuf_lastindex];
888f1c579b1SScott Long 					memcpy(pQbuffer, iop_data, 1);
889ad6d6297SScott Long 					acb->rqbuf_lastindex++;
890ad6d6297SScott Long 					acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER;
891ad6d6297SScott Long 					/*if last index number set it to 0 */
892f1c579b1SScott Long 					iop_data++;
893f1c579b1SScott Long 					iop_len--;
894f1c579b1SScott Long 				}
895ad6d6297SScott Long 				CHIP_REG_WRITE32(inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK);
896ad6d6297SScott Long 				/*signature, let IOP331 know data has been readed */
897f1c579b1SScott Long 			}
898ad6d6297SScott Long 			pcmdmessagefld->cmdmessage.Length=allxfer_len;
899ad6d6297SScott Long 			pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK;
900ad6d6297SScott Long 			retvalue=ARCMSR_MESSAGE_SUCCESS;
901f1c579b1SScott Long  		}
902f1c579b1SScott Long 		break;
903ad6d6297SScott Long 	case ARCMSR_MESSAGE_WRITE_WQBUFFER: {
904ad6d6297SScott Long 			u_int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex;
905ad6d6297SScott Long 			u_int8_t * pQbuffer;
906ad6d6297SScott Long 			u_int8_t * ptmpuserbuffer=pcmdmessagefld->messagedatabuffer;
907f1c579b1SScott Long 
908ad6d6297SScott Long 			user_len=pcmdmessagefld->cmdmessage.Length;
909f1c579b1SScott Long 			/*check if data xfer length of this request will overflow my array qbuffer */
910ad6d6297SScott Long 			wqbuf_lastindex=acb->wqbuf_lastindex;
911ad6d6297SScott Long 			wqbuf_firstindex=acb->wqbuf_firstindex;
912ad6d6297SScott Long 			if(wqbuf_lastindex!=wqbuf_firstindex) {
913ad6d6297SScott Long 				arcmsr_post_Qbuffer(acb);
914ad6d6297SScott Long 				pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_ERROR;
915ad6d6297SScott Long 			} else {
916f1c579b1SScott Long 				my_empty_len=(wqbuf_firstindex-wqbuf_lastindex-1)&(ARCMSR_MAX_QBUFFER-1);
917ad6d6297SScott Long 				if(my_empty_len>=user_len) {
918ad6d6297SScott Long 					while(user_len>0) {
919f1c579b1SScott Long 						/*copy srb data to wqbuffer*/
920ad6d6297SScott Long 						pQbuffer= &acb->wqbuffer[acb->wqbuf_lastindex];
921f1c579b1SScott Long 						memcpy(pQbuffer, ptmpuserbuffer, 1);
922ad6d6297SScott Long 						acb->wqbuf_lastindex++;
923ad6d6297SScott Long 						acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER;
924ad6d6297SScott Long 						/*if last index number set it to 0 */
925f1c579b1SScott Long  						ptmpuserbuffer++;
926f1c579b1SScott Long 						user_len--;
927f1c579b1SScott Long 					}
928f1c579b1SScott Long 					/*post fist Qbuffer*/
929ad6d6297SScott Long 					if(acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) {
930ad6d6297SScott Long 						acb->acb_flags &=~ACB_F_MESSAGE_WQBUFFER_CLEARED;
931ad6d6297SScott Long  						arcmsr_post_Qbuffer(acb);
932f1c579b1SScott Long 					}
933ad6d6297SScott Long 					pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK;
934ad6d6297SScott Long 				} else {
935ad6d6297SScott Long 					pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_ERROR;
936f1c579b1SScott Long 				}
937f1c579b1SScott Long 			}
938ad6d6297SScott Long 			retvalue=ARCMSR_MESSAGE_SUCCESS;
939f1c579b1SScott Long 		}
940f1c579b1SScott Long 		break;
941ad6d6297SScott Long 	case ARCMSR_MESSAGE_CLEAR_RQBUFFER: {
942ad6d6297SScott Long 			u_int8_t * pQbuffer=acb->rqbuffer;
943ad6d6297SScott Long 
944ad6d6297SScott Long 			if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
945ad6d6297SScott Long 				acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
946ad6d6297SScott Long 				CHIP_REG_WRITE32(inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK);
947ad6d6297SScott Long 				/*signature, let IOP331 know data has been readed */
948f1c579b1SScott Long 			}
949ad6d6297SScott Long 			acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED;
950ad6d6297SScott Long 			acb->rqbuf_firstindex=0;
951ad6d6297SScott Long 			acb->rqbuf_lastindex=0;
952f1c579b1SScott Long 			memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER);
953ad6d6297SScott Long 			pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK;
954ad6d6297SScott Long 			retvalue=ARCMSR_MESSAGE_SUCCESS;
955f1c579b1SScott Long 		}
956f1c579b1SScott Long 		break;
957ad6d6297SScott Long 	case ARCMSR_MESSAGE_CLEAR_WQBUFFER:
958f1c579b1SScott Long 		{
959ad6d6297SScott Long 			u_int8_t * pQbuffer=acb->wqbuffer;
960f1c579b1SScott Long 
961ad6d6297SScott Long 			if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
962ad6d6297SScott Long 				acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
963ad6d6297SScott Long 				CHIP_REG_WRITE32(inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK);
964ad6d6297SScott Long 				/*signature, let IOP331 know data has been readed */
965f1c579b1SScott Long 			}
966ad6d6297SScott Long 			acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED|ACB_F_MESSAGE_WQBUFFER_READED);
967ad6d6297SScott Long 			acb->wqbuf_firstindex=0;
968ad6d6297SScott Long 			acb->wqbuf_lastindex=0;
969f1c579b1SScott Long 			memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER);
970ad6d6297SScott Long 			pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK;
971ad6d6297SScott Long 			retvalue=ARCMSR_MESSAGE_SUCCESS;
972f1c579b1SScott Long 		}
973f1c579b1SScott Long 		break;
974ad6d6297SScott Long 	case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER: {
975ad6d6297SScott Long 			u_int8_t * pQbuffer;
976f1c579b1SScott Long 
977ad6d6297SScott Long 			if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
978ad6d6297SScott Long 				acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
979ad6d6297SScott Long 				CHIP_REG_WRITE32(inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK);
980ad6d6297SScott Long 				/*signature, let IOP331 know data has been readed */
981f1c579b1SScott Long 			}
982ad6d6297SScott Long 			acb->acb_flags  |= (ACB_F_MESSAGE_WQBUFFER_CLEARED
983ad6d6297SScott Long 					|ACB_F_MESSAGE_RQBUFFER_CLEARED
984ad6d6297SScott Long 					|ACB_F_MESSAGE_WQBUFFER_READED);
985ad6d6297SScott Long 			acb->rqbuf_firstindex=0;
986ad6d6297SScott Long 			acb->rqbuf_lastindex=0;
987ad6d6297SScott Long 			acb->wqbuf_firstindex=0;
988ad6d6297SScott Long 			acb->wqbuf_lastindex=0;
989ad6d6297SScott Long 			pQbuffer=acb->rqbuffer;
990ad6d6297SScott Long 			memset(pQbuffer, 0, sizeof(struct QBUFFER));
991ad6d6297SScott Long 			pQbuffer=acb->wqbuffer;
992ad6d6297SScott Long 			memset(pQbuffer, 0, sizeof(struct QBUFFER));
993ad6d6297SScott Long 			pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK;
994ad6d6297SScott Long 			retvalue=ARCMSR_MESSAGE_SUCCESS;
995f1c579b1SScott Long 		}
996f1c579b1SScott Long 		break;
997ad6d6297SScott Long 	case ARCMSR_MESSAGE_REQUEST_RETURNCODE_3F: {
998ad6d6297SScott Long 			pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_3F;
999ad6d6297SScott Long 			retvalue=ARCMSR_MESSAGE_SUCCESS;
1000f1c579b1SScott Long 		}
1001f1c579b1SScott Long 		break;
1002ad6d6297SScott Long 	case ARCMSR_MESSAGE_SAY_HELLO: {
1003ad6d6297SScott Long 			u_int8_t * hello_string="Hello! I am ARCMSR";
1004ad6d6297SScott Long 			u_int8_t * puserbuffer=(u_int8_t *)pcmdmessagefld->messagedatabuffer;
1005f1c579b1SScott Long 
1006ad6d6297SScott Long 			if(memcpy(puserbuffer, hello_string, (int16_t)strlen(hello_string))) {
1007ad6d6297SScott Long 				pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_ERROR;
1008ad6d6297SScott Long 				ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
1009f1c579b1SScott Long 				return ENOIOCTL;
1010f1c579b1SScott Long 			}
1011ad6d6297SScott Long 			pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK;
1012ad6d6297SScott Long 			retvalue=ARCMSR_MESSAGE_SUCCESS;
1013ad6d6297SScott Long 		}
1014ad6d6297SScott Long 		break;
1015ad6d6297SScott Long 	case ARCMSR_MESSAGE_SAY_GOODBYE: {
1016ad6d6297SScott Long 			arcmsr_iop_parking(acb);
1017ad6d6297SScott Long 			retvalue=ARCMSR_MESSAGE_SUCCESS;
1018ad6d6297SScott Long 		}
1019ad6d6297SScott Long 		break;
1020ad6d6297SScott Long     case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE: {
1021ad6d6297SScott Long 			arcmsr_flush_adapter_cache(acb);
1022ad6d6297SScott Long 			retvalue=ARCMSR_MESSAGE_SUCCESS;
1023f1c579b1SScott Long 		}
1024f1c579b1SScott Long 		break;
1025f1c579b1SScott Long 	}
1026ad6d6297SScott Long 	ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
1027ad6d6297SScott Long 	return retvalue;
1028f1c579b1SScott Long }
1029f1c579b1SScott Long /*
1030f1c579b1SScott Long **************************************************************************
1031f1c579b1SScott Long **************************************************************************
1032f1c579b1SScott Long */
1033ad6d6297SScott Long struct CommandControlBlock * arcmsr_get_freesrb(struct AdapterControlBlock *acb)
1034f1c579b1SScott Long {
1035ad6d6297SScott Long 	struct CommandControlBlock *srb=NULL;
1036ad6d6297SScott Long 	u_int32_t workingsrb_startindex, workingsrb_doneindex;
1037f1c579b1SScott Long 
1038ad6d6297SScott Long 	ARCMSR_LOCK_ACQUIRE(&acb->workingQ_start_lock);
1039ad6d6297SScott Long 	workingsrb_doneindex=acb->workingsrb_doneindex;
1040ad6d6297SScott Long 	workingsrb_startindex=acb->workingsrb_startindex;
1041ad6d6297SScott Long 	srb=acb->srbworkingQ[workingsrb_startindex];
1042ad6d6297SScott Long 	workingsrb_startindex++;
1043ad6d6297SScott Long 	workingsrb_startindex %= ARCMSR_MAX_FREESRB_NUM;
1044ad6d6297SScott Long 	if(workingsrb_doneindex!=workingsrb_startindex) {
1045ad6d6297SScott Long 		acb->workingsrb_startindex=workingsrb_startindex;
1046ad6d6297SScott Long 	} else {
1047ad6d6297SScott Long 		srb=NULL;
1048ad6d6297SScott Long 	}
1049ad6d6297SScott Long 	ARCMSR_LOCK_RELEASE(&acb->workingQ_start_lock);
1050ad6d6297SScott Long 	return(srb);
1051ad6d6297SScott Long }
1052ad6d6297SScott Long /*
1053ad6d6297SScott Long **************************************************************************
1054ad6d6297SScott Long **************************************************************************
1055ad6d6297SScott Long */
1056ad6d6297SScott Long static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb * pccb)
1057ad6d6297SScott Long {
1058ad6d6297SScott Long 	struct CMD_MESSAGE_FIELD * pcmdmessagefld;
1059ad6d6297SScott Long 	int retvalue = 0, transfer_len = 0;
1060ad6d6297SScott Long 	char *buffer;
1061ad6d6297SScott Long 	uint32_t controlcode = (uint32_t ) pccb->csio.cdb_io.cdb_bytes[5] << 24 |
1062ad6d6297SScott Long 						(uint32_t ) pccb->csio.cdb_io.cdb_bytes[6] << 16 |
1063ad6d6297SScott Long 						(uint32_t ) pccb->csio.cdb_io.cdb_bytes[7] << 8  |
1064ad6d6297SScott Long 						(uint32_t ) pccb->csio.cdb_io.cdb_bytes[8];
1065ad6d6297SScott Long 					/* 4 bytes: Areca io control code */
1066ad6d6297SScott Long 	if((pccb->ccb_h.flags & CAM_SCATTER_VALID) == 0) {
1067ad6d6297SScott Long 		buffer = pccb->csio.data_ptr;
1068ad6d6297SScott Long 		transfer_len = pccb->csio.dxfer_len;
1069ad6d6297SScott Long 	} else {
1070ad6d6297SScott Long 		retvalue = ARCMSR_MESSAGE_FAIL;
1071ad6d6297SScott Long 		goto message_out;
1072ad6d6297SScott Long 	}
1073ad6d6297SScott Long 	if (transfer_len > sizeof(struct CMD_MESSAGE_FIELD)) {
1074ad6d6297SScott Long 		retvalue = ARCMSR_MESSAGE_FAIL;
1075ad6d6297SScott Long 		goto message_out;
1076ad6d6297SScott Long 	}
1077ad6d6297SScott Long 	pcmdmessagefld = (struct CMD_MESSAGE_FIELD *) buffer;
1078ad6d6297SScott Long 	switch(controlcode) {
1079ad6d6297SScott Long 	case ARCMSR_MESSAGE_READ_RQBUFFER: {
1080ad6d6297SScott Long 			u_int8_t *pQbuffer;
1081ad6d6297SScott Long 			u_int8_t *ptmpQbuffer=pcmdmessagefld->messagedatabuffer;
1082ad6d6297SScott Long 			int32_t allxfer_len = 0;
1083f1c579b1SScott Long 
1084ad6d6297SScott Long 			while ((acb->rqbuf_firstindex != acb->rqbuf_lastindex)
1085ad6d6297SScott Long 				&& (allxfer_len < 1031)) {
1086ad6d6297SScott Long 				pQbuffer = &acb->rqbuffer[acb->rqbuf_firstindex];
1087ad6d6297SScott Long 				memcpy(ptmpQbuffer, pQbuffer, 1);
1088ad6d6297SScott Long 				acb->rqbuf_firstindex++;
1089ad6d6297SScott Long 				acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER;
1090ad6d6297SScott Long 				ptmpQbuffer++;
1091ad6d6297SScott Long 				allxfer_len++;
1092f1c579b1SScott Long 			}
1093ad6d6297SScott Long 			if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
1094ad6d6297SScott Long 				struct QBUFFER  *prbuffer = (struct QBUFFER  *) &acb->pmu->message_rbuffer;
1095ad6d6297SScott Long 				u_int8_t  *iop_data = (u_int8_t *)prbuffer->data;
1096ad6d6297SScott Long 				int32_t iop_len;
1097ad6d6297SScott Long 
1098ad6d6297SScott Long 				acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
1099ad6d6297SScott Long 				iop_len =(u_int32_t)prbuffer->data_len;
1100ad6d6297SScott Long 				while (iop_len > 0) {
1101ad6d6297SScott Long 			        pQbuffer= &acb->rqbuffer[acb->rqbuf_lastindex];
1102ad6d6297SScott Long 					memcpy(pQbuffer, iop_data, 1);
1103ad6d6297SScott Long 					acb->rqbuf_lastindex++;
1104ad6d6297SScott Long 					acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER;
1105ad6d6297SScott Long 					iop_data++;
1106ad6d6297SScott Long 					iop_len--;
1107f1c579b1SScott Long 				}
1108ad6d6297SScott Long 				CHIP_REG_WRITE32(inbound_doorbell,
1109ad6d6297SScott Long 						ARCMSR_INBOUND_DRIVER_DATA_READ_OK);
1110ad6d6297SScott Long 			}
1111ad6d6297SScott Long 			pcmdmessagefld->cmdmessage.Length = allxfer_len;
1112ad6d6297SScott Long 			pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
1113ad6d6297SScott Long 			retvalue=ARCMSR_MESSAGE_SUCCESS;
1114ad6d6297SScott Long 		}
1115ad6d6297SScott Long 		break;
1116ad6d6297SScott Long 	case ARCMSR_MESSAGE_WRITE_WQBUFFER: {
1117ad6d6297SScott Long 			int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex;
1118ad6d6297SScott Long 			u_int8_t *pQbuffer;
1119ad6d6297SScott Long 			u_int8_t *ptmpuserbuffer=pcmdmessagefld->messagedatabuffer;
1120ad6d6297SScott Long 
1121ad6d6297SScott Long 			user_len = pcmdmessagefld->cmdmessage.Length;
1122ad6d6297SScott Long 			wqbuf_lastindex = acb->wqbuf_lastindex;
1123ad6d6297SScott Long 			wqbuf_firstindex = acb->wqbuf_firstindex;
1124ad6d6297SScott Long 			if (wqbuf_lastindex != wqbuf_firstindex) {
1125ad6d6297SScott Long 				arcmsr_post_Qbuffer(acb);
1126ad6d6297SScott Long 				/* has error report sensedata */
1127ad6d6297SScott Long 			    if(&pccb->csio.sense_data) {
1128ad6d6297SScott Long 				((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70);
1129ad6d6297SScott Long 				/* Valid,ErrorCode */
1130ad6d6297SScott Long 				((u_int8_t *)&pccb->csio.sense_data)[2] = 0x05;
1131ad6d6297SScott Long 				/* FileMark,EndOfMedia,IncorrectLength,Reserved,SenseKey */
1132ad6d6297SScott Long 				((u_int8_t *)&pccb->csio.sense_data)[7] = 0x0A;
1133ad6d6297SScott Long 				/* AdditionalSenseLength */
1134ad6d6297SScott Long 				((u_int8_t *)&pccb->csio.sense_data)[12] = 0x20;
1135ad6d6297SScott Long 				/* AdditionalSenseCode */
1136ad6d6297SScott Long 				}
1137ad6d6297SScott Long 				retvalue = ARCMSR_MESSAGE_FAIL;
1138ad6d6297SScott Long 			} else {
1139ad6d6297SScott Long 				my_empty_len = (wqbuf_firstindex-wqbuf_lastindex - 1)
1140ad6d6297SScott Long 						&(ARCMSR_MAX_QBUFFER - 1);
1141ad6d6297SScott Long 				if (my_empty_len >= user_len) {
1142ad6d6297SScott Long 					while (user_len > 0) {
1143ad6d6297SScott Long 						pQbuffer = &acb->wqbuffer[acb->wqbuf_lastindex];
1144ad6d6297SScott Long 						memcpy(pQbuffer, ptmpuserbuffer, 1);
1145ad6d6297SScott Long 						acb->wqbuf_lastindex++;
1146ad6d6297SScott Long 						acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER;
1147ad6d6297SScott Long 						ptmpuserbuffer++;
1148ad6d6297SScott Long 						user_len--;
1149ad6d6297SScott Long 					}
1150ad6d6297SScott Long 					if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) {
1151ad6d6297SScott Long 						acb->acb_flags &=
1152ad6d6297SScott Long 						~ACB_F_MESSAGE_WQBUFFER_CLEARED;
1153ad6d6297SScott Long 						arcmsr_post_Qbuffer(acb);
1154ad6d6297SScott Long 					}
1155ad6d6297SScott Long 				} else {
1156ad6d6297SScott Long 					/* has error report sensedata */
1157ad6d6297SScott Long 					if(&pccb->csio.sense_data) {
1158ad6d6297SScott Long 					((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70);
1159ad6d6297SScott Long 					/* Valid,ErrorCode */
1160ad6d6297SScott Long 					((u_int8_t *)&pccb->csio.sense_data)[2] = 0x05;
1161ad6d6297SScott Long 					/* FileMark,EndOfMedia,IncorrectLength,Reserved,SenseKey */
1162ad6d6297SScott Long 					((u_int8_t *)&pccb->csio.sense_data)[7] = 0x0A;
1163ad6d6297SScott Long 					/* AdditionalSenseLength */
1164ad6d6297SScott Long 					((u_int8_t *)&pccb->csio.sense_data)[12] = 0x20;
1165ad6d6297SScott Long 					/* AdditionalSenseCode */
1166ad6d6297SScott Long 					}
1167ad6d6297SScott Long 					retvalue = ARCMSR_MESSAGE_FAIL;
1168ad6d6297SScott Long 				}
1169ad6d6297SScott Long 			}
1170ad6d6297SScott Long 		}
1171ad6d6297SScott Long 		break;
1172ad6d6297SScott Long 	case ARCMSR_MESSAGE_CLEAR_RQBUFFER: {
1173ad6d6297SScott Long 			u_int8_t *pQbuffer = acb->rqbuffer;
1174ad6d6297SScott Long 
1175ad6d6297SScott Long 			if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
1176ad6d6297SScott Long 				acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
1177ad6d6297SScott Long 				CHIP_REG_WRITE32(inbound_doorbell
1178ad6d6297SScott Long 					, ARCMSR_INBOUND_DRIVER_DATA_READ_OK);
1179ad6d6297SScott Long 			}
1180ad6d6297SScott Long 			acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED;
1181ad6d6297SScott Long 			acb->rqbuf_firstindex = 0;
1182ad6d6297SScott Long 			acb->rqbuf_lastindex = 0;
1183ad6d6297SScott Long 			memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER);
1184ad6d6297SScott Long 			pcmdmessagefld->cmdmessage.ReturnCode =
1185ad6d6297SScott Long 			ARCMSR_MESSAGE_RETURNCODE_OK;
1186ad6d6297SScott Long 		}
1187ad6d6297SScott Long 		break;
1188ad6d6297SScott Long 	case ARCMSR_MESSAGE_CLEAR_WQBUFFER: {
1189ad6d6297SScott Long 			u_int8_t *pQbuffer = acb->wqbuffer;
1190ad6d6297SScott Long 
1191ad6d6297SScott Long 			if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
1192ad6d6297SScott Long 				acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
1193ad6d6297SScott Long 				CHIP_REG_WRITE32(inbound_doorbell
1194ad6d6297SScott Long 						, ARCMSR_INBOUND_DRIVER_DATA_READ_OK);
1195ad6d6297SScott Long 			}
1196ad6d6297SScott Long 			acb->acb_flags |=
1197ad6d6297SScott Long 				(ACB_F_MESSAGE_WQBUFFER_CLEARED |
1198ad6d6297SScott Long 					ACB_F_MESSAGE_WQBUFFER_READED);
1199ad6d6297SScott Long 			acb->wqbuf_firstindex = 0;
1200ad6d6297SScott Long 			acb->wqbuf_lastindex = 0;
1201ad6d6297SScott Long 			memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER);
1202ad6d6297SScott Long 			pcmdmessagefld->cmdmessage.ReturnCode =
1203ad6d6297SScott Long 				ARCMSR_MESSAGE_RETURNCODE_OK;
1204ad6d6297SScott Long 		}
1205ad6d6297SScott Long 		break;
1206ad6d6297SScott Long 	case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER: {
1207ad6d6297SScott Long 			u_int8_t *pQbuffer;
1208ad6d6297SScott Long 
1209ad6d6297SScott Long 			if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
1210ad6d6297SScott Long 				acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
1211ad6d6297SScott Long 				CHIP_REG_WRITE32(inbound_doorbell
1212ad6d6297SScott Long 						, ARCMSR_INBOUND_DRIVER_DATA_READ_OK);
1213ad6d6297SScott Long 			}
1214ad6d6297SScott Long 			acb->acb_flags |=
1215ad6d6297SScott Long 				(ACB_F_MESSAGE_WQBUFFER_CLEARED
1216ad6d6297SScott Long 				| ACB_F_MESSAGE_RQBUFFER_CLEARED
1217ad6d6297SScott Long 				| ACB_F_MESSAGE_WQBUFFER_READED);
1218ad6d6297SScott Long 			acb->rqbuf_firstindex = 0;
1219ad6d6297SScott Long 			acb->rqbuf_lastindex = 0;
1220ad6d6297SScott Long 			acb->wqbuf_firstindex = 0;
1221ad6d6297SScott Long 			acb->wqbuf_lastindex = 0;
1222ad6d6297SScott Long 			pQbuffer = acb->rqbuffer;
1223ad6d6297SScott Long 			memset(pQbuffer, 0, sizeof (struct QBUFFER));
1224ad6d6297SScott Long 			pQbuffer = acb->wqbuffer;
1225ad6d6297SScott Long 			memset(pQbuffer, 0, sizeof (struct QBUFFER));
1226ad6d6297SScott Long 			pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
1227ad6d6297SScott Long 		}
1228ad6d6297SScott Long 		break;
1229ad6d6297SScott Long 	case ARCMSR_MESSAGE_REQUEST_RETURNCODE_3F: {
1230ad6d6297SScott Long 			pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_3F;
1231ad6d6297SScott Long 		}
1232ad6d6297SScott Long 		break;
1233ad6d6297SScott Long 	case ARCMSR_MESSAGE_SAY_HELLO: {
1234ad6d6297SScott Long 			int8_t * hello_string = "Hello! I am ARCMSR";
1235ad6d6297SScott Long 
1236ad6d6297SScott Long 			memcpy(pcmdmessagefld->messagedatabuffer, hello_string
1237ad6d6297SScott Long 				, (int16_t)strlen(hello_string));
1238ad6d6297SScott Long 			pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
1239ad6d6297SScott Long 		}
1240ad6d6297SScott Long 		break;
1241ad6d6297SScott Long 	case ARCMSR_MESSAGE_SAY_GOODBYE:
1242ad6d6297SScott Long 		arcmsr_iop_parking(acb);
1243ad6d6297SScott Long 		break;
1244ad6d6297SScott Long 	case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE:
1245ad6d6297SScott Long 		arcmsr_flush_adapter_cache(acb);
1246ad6d6297SScott Long 		break;
1247ad6d6297SScott Long 	default:
1248ad6d6297SScott Long 		retvalue = ARCMSR_MESSAGE_FAIL;
1249ad6d6297SScott Long 	}
1250ad6d6297SScott Long message_out:
1251ad6d6297SScott Long 	return retvalue;
1252f1c579b1SScott Long }
1253f1c579b1SScott Long /*
1254f1c579b1SScott Long *********************************************************************
1255f1c579b1SScott Long *********************************************************************
1256f1c579b1SScott Long */
1257ad6d6297SScott Long static void arcmsr_executesrb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
1258f1c579b1SScott Long {
1259ad6d6297SScott Long 	struct CommandControlBlock *srb=(struct CommandControlBlock *)arg;
1260ad6d6297SScott Long 	struct AdapterControlBlock *acb=(struct AdapterControlBlock *)srb->acb;
1261f1c579b1SScott Long 	union ccb * pccb;
1262ad6d6297SScott Long 	int target, lun;
1263f1c579b1SScott Long 
1264ad6d6297SScott Long 	pccb=srb->pccb;
1265ad6d6297SScott Long 	target=pccb->ccb_h.target_id;
1266ad6d6297SScott Long 	lun=pccb->ccb_h.target_lun;
1267ad6d6297SScott Long 	if(error != 0) {
1268ad6d6297SScott Long 		if(error != EFBIG) {
1269ad6d6297SScott Long 			printf("arcmsr%d: unexpected error %x returned from 'bus_dmamap_load' \n"
1270ad6d6297SScott Long 				, acb->pci_unit, error);
1271f1c579b1SScott Long 		}
1272ad6d6297SScott Long 		if((pccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) {
127315735becSScott Long 			pccb->ccb_h.status |= CAM_REQ_TOO_BIG;
1274f1c579b1SScott Long 		}
1275ad6d6297SScott Long 		arcmsr_srb_complete(srb, 0);
1276f1c579b1SScott Long 		return;
1277f1c579b1SScott Long 	}
1278ad6d6297SScott Long 	if(nseg > ARCMSR_MAX_SG_ENTRIES) {
1279ad6d6297SScott Long 		pccb->ccb_h.status |= CAM_REQ_TOO_BIG;
1280ad6d6297SScott Long 		arcmsr_srb_complete(srb, 0);
1281ad6d6297SScott Long 		return;
1282f1c579b1SScott Long 	}
1283ad6d6297SScott Long  	if(acb->acb_flags & ACB_F_BUS_RESET) {
1284ad6d6297SScott Long 		printf("arcmsr%d: bus reset and return busy \n", acb->pci_unit);
1285ad6d6297SScott Long 		pccb->ccb_h.status |= CAM_SCSI_BUS_RESET;
1286ad6d6297SScott Long 		arcmsr_srb_complete(srb, 0);
1287ad6d6297SScott Long 		return;
1288ad6d6297SScott Long 	}
1289ad6d6297SScott Long 	if(acb->devstate[target][lun]==ARECA_RAID_GONE) {
1290ad6d6297SScott Long 		u_int8_t block_cmd;
1291ad6d6297SScott Long 
1292ad6d6297SScott Long 		block_cmd=pccb->csio.cdb_io.cdb_bytes[0] & 0x0f;
1293ad6d6297SScott Long 		if(block_cmd==0x08 || block_cmd==0x0a) {
1294ad6d6297SScott Long 			printf("arcmsr%d:block 'read/write' command"
1295ad6d6297SScott Long 				"with gone raid volume Cmd=%2x, TargetId=%d, Lun=%d \n"
1296ad6d6297SScott Long 				, acb->pci_unit, block_cmd, target, lun);
1297ad6d6297SScott Long 			pccb->ccb_h.status |= CAM_DEV_NOT_THERE;
1298ad6d6297SScott Long 			arcmsr_srb_complete(srb, 0);
1299ad6d6297SScott Long 			return;
1300ad6d6297SScott Long 		}
1301ad6d6297SScott Long 	}
1302ad6d6297SScott Long 	if((pccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_INPROG) {
1303ad6d6297SScott Long 		if(nseg != 0) {
1304ad6d6297SScott Long 			bus_dmamap_unload(acb->dm_segs_dmat, srb->dm_segs_dmamap);
1305ad6d6297SScott Long 		}
1306ad6d6297SScott Long 		arcmsr_srb_complete(srb, 0);
1307f1c579b1SScott Long 		return;
1308f1c579b1SScott Long 	}
1309ad6d6297SScott Long 	if(acb->srboutstandingcount >= ARCMSR_MAX_OUTSTANDING_CMD) {
131015735becSScott Long 		xpt_freeze_simq(acb->psim, 1);
131115735becSScott Long 		pccb->ccb_h.status = CAM_REQUEUE_REQ;
1312dc3a205bSScott Long 		acb->acb_flags |= ACB_F_CAM_DEV_QFRZN;
1313ad6d6297SScott Long 		arcmsr_srb_complete(srb, 0);
1314ad6d6297SScott Long 		return;
1315f1c579b1SScott Long 	}
131615735becSScott Long 	pccb->ccb_h.status |= CAM_SIM_QUEUED;
1317ad6d6297SScott Long 	arcmsr_build_srb(srb, dm_segs, nseg);
1318ad6d6297SScott Long 	arcmsr_post_srb(acb, srb);
1319f1c579b1SScott Long 	return;
1320f1c579b1SScott Long }
1321f1c579b1SScott Long /*
1322f1c579b1SScott Long *****************************************************************************************
1323f1c579b1SScott Long *****************************************************************************************
1324f1c579b1SScott Long */
1325ad6d6297SScott Long static u_int8_t arcmsr_seek_cmd2abort(union ccb * abortccb)
1326f1c579b1SScott Long {
1327ad6d6297SScott Long 	struct CommandControlBlock *srb;
1328ad6d6297SScott Long 	struct AdapterControlBlock *acb=(struct AdapterControlBlock *) abortccb->ccb_h.arcmsr_ccbacb_ptr;
1329ad6d6297SScott Long 	u_int32_t intmask_org, mask;
1330ad6d6297SScott Long 	int i=0;
1331f1c579b1SScott Long 
1332ad6d6297SScott Long 	acb->num_aborts++;
1333f1c579b1SScott Long 	/*
1334ad6d6297SScott Long 	***************************************************************************
1335f1c579b1SScott Long 	** It is the upper layer do abort command this lock just prior to calling us.
1336f1c579b1SScott Long 	** First determine if we currently own this command.
1337f1c579b1SScott Long 	** Start by searching the device queue. If not found
1338f1c579b1SScott Long 	** at all, and the system wanted us to just abort the
1339f1c579b1SScott Long 	** command return success.
1340ad6d6297SScott Long 	***************************************************************************
1341f1c579b1SScott Long 	*/
1342ad6d6297SScott Long 	if(acb->srboutstandingcount!=0) {
1343ad6d6297SScott Long 		for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++) {
1344ad6d6297SScott Long 			srb=acb->psrb_pool[i];
1345ad6d6297SScott Long 			if(srb->startdone==ARCMSR_SRB_START) {
1346ad6d6297SScott Long 				if(srb->pccb==abortccb) {
1347ad6d6297SScott Long 					srb->startdone=ARCMSR_SRB_ABORTED;
1348ad6d6297SScott Long 					printf("arcmsr%d:scsi id=%d lun=%d abort srb '%p'"
1349ad6d6297SScott Long 						"outstanding command \n"
1350ad6d6297SScott Long 						, acb->pci_unit, abortccb->ccb_h.target_id
1351ad6d6297SScott Long 						, abortccb->ccb_h.target_lun, srb);
1352ad6d6297SScott Long 					goto abort_outstanding_cmd;
1353f1c579b1SScott Long 				}
1354f1c579b1SScott Long 			}
1355f1c579b1SScott Long 		}
1356f1c579b1SScott Long 	}
1357f1c579b1SScott Long 	return(FALSE);
1358ad6d6297SScott Long abort_outstanding_cmd:
1359ad6d6297SScott Long 	/* do not talk to iop 331 abort command */
1360ad6d6297SScott Long 	UDELAY(3000*1000);/*wait for 3 sec for all command done*/
1361ad6d6297SScott Long 	/* disable all outbound interrupt */
1362ad6d6297SScott Long 	intmask_org=CHIP_REG_READ32(outbound_intmask);
1363ad6d6297SScott Long 	CHIP_REG_WRITE32(outbound_intmask, intmask_org|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE);
1364ad6d6297SScott Long 	arcmsr_polling_srbdone(acb, srb);
1365ad6d6297SScott Long 	/* enable all outbound interrupt */
1366ad6d6297SScott Long 	mask=~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE|ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE);
1367ad6d6297SScott Long 	CHIP_REG_WRITE32(outbound_intmask, intmask_org & mask);
1368ad6d6297SScott Long 	return (TRUE);
1369f1c579b1SScott Long }
1370f1c579b1SScott Long /*
1371f1c579b1SScott Long ****************************************************************************
1372f1c579b1SScott Long ****************************************************************************
1373f1c579b1SScott Long */
1374ad6d6297SScott Long static void arcmsr_bus_reset(struct AdapterControlBlock *acb)
1375f1c579b1SScott Long {
1376ad6d6297SScott Long 	int retry=0;
1377f1c579b1SScott Long 
1378ad6d6297SScott Long 	acb->num_resets++;
1379ad6d6297SScott Long 	acb->acb_flags |=ACB_F_BUS_RESET;
1380ad6d6297SScott Long 	while(acb->srboutstandingcount!=0 && retry < 400) {
1381ad6d6297SScott Long 		arcmsr_interrupt((void *)acb);
1382ad6d6297SScott Long 		UDELAY(25000);
1383ad6d6297SScott Long 		retry++;
1384ad6d6297SScott Long 	}
1385ad6d6297SScott Long 	arcmsr_iop_reset(acb);
1386ad6d6297SScott Long 	acb->acb_flags &= ~ACB_F_BUS_RESET;
1387f1c579b1SScott Long 	return;
1388f1c579b1SScott Long }
1389f1c579b1SScott Long /*
1390ad6d6297SScott Long **************************************************************************
1391ad6d6297SScott Long **************************************************************************
1392ad6d6297SScott Long */
1393ad6d6297SScott Long static void arcmsr_handle_virtual_command(struct AdapterControlBlock *acb,
1394ad6d6297SScott Long 		union ccb * pccb)
1395ad6d6297SScott Long {
1396ad6d6297SScott Long 	pccb->ccb_h.status |= CAM_REQ_CMP;
1397ad6d6297SScott Long 	switch (pccb->csio.cdb_io.cdb_bytes[0]) {
1398ad6d6297SScott Long 	case INQUIRY: {
1399ad6d6297SScott Long 		unsigned char inqdata[36];
1400ad6d6297SScott Long 		char *buffer=pccb->csio.data_ptr;;
1401ad6d6297SScott Long 
1402ad6d6297SScott Long 		if (pccb->ccb_h.target_lun) {
1403ad6d6297SScott Long 			pccb->ccb_h.status |= CAM_SEL_TIMEOUT;
1404ad6d6297SScott Long 			xpt_done(pccb);
1405ad6d6297SScott Long 			return;
1406ad6d6297SScott Long 		}
1407ad6d6297SScott Long 		inqdata[0] = T_PROCESSOR;
1408ad6d6297SScott Long 		/* Periph Qualifier & Periph Dev Type */
1409ad6d6297SScott Long 		inqdata[1] = 0;
1410ad6d6297SScott Long 		/* rem media bit & Dev Type Modifier */
1411ad6d6297SScott Long 		inqdata[2] = 0;
1412ad6d6297SScott Long 		/* ISO, ECMA, & ANSI versions */
1413ad6d6297SScott Long 		inqdata[4] = 31;
1414ad6d6297SScott Long 		/* length of additional data */
1415ad6d6297SScott Long 		strncpy(&inqdata[8], "Areca   ", 8);
1416ad6d6297SScott Long 		/* Vendor Identification */
1417ad6d6297SScott Long 		strncpy(&inqdata[16], "RAID controller ", 16);
1418ad6d6297SScott Long 		/* Product Identification */
1419ad6d6297SScott Long 		strncpy(&inqdata[32], "R001", 4); /* Product Revision */
1420ad6d6297SScott Long 		memcpy(buffer, inqdata, sizeof(inqdata));
1421ad6d6297SScott Long 		xpt_done(pccb);
1422ad6d6297SScott Long 	}
1423ad6d6297SScott Long 	break;
1424ad6d6297SScott Long 	case WRITE_BUFFER:
1425ad6d6297SScott Long 	case READ_BUFFER: {
1426ad6d6297SScott Long 		if (arcmsr_iop_message_xfer(acb, pccb)) {
1427ad6d6297SScott Long 			pccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
1428ad6d6297SScott Long 			pccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
1429ad6d6297SScott Long 		}
1430ad6d6297SScott Long 		xpt_done(pccb);
1431ad6d6297SScott Long 	}
1432ad6d6297SScott Long 	break;
1433ad6d6297SScott Long 	default:
1434ad6d6297SScott Long 		xpt_done(pccb);
1435ad6d6297SScott Long 	}
1436ad6d6297SScott Long }
1437ad6d6297SScott Long /*
1438f1c579b1SScott Long *********************************************************************
1439f1c579b1SScott Long *********************************************************************
1440f1c579b1SScott Long */
1441ad6d6297SScott Long static void arcmsr_action(struct cam_sim * psim, union ccb * pccb)
1442f1c579b1SScott Long {
1443ad6d6297SScott Long 	struct AdapterControlBlock *  acb;
1444f1c579b1SScott Long 
1445ad6d6297SScott Long 	acb=(struct AdapterControlBlock *) cam_sim_softc(psim);
1446ad6d6297SScott Long 	if(acb==NULL) {
1447ad6d6297SScott Long 		pccb->ccb_h.status |= CAM_REQ_INVALID;
1448f1c579b1SScott Long 		xpt_done(pccb);
1449f1c579b1SScott Long 		return;
1450f1c579b1SScott Long 	}
1451ad6d6297SScott Long 	switch (pccb->ccb_h.func_code) {
1452ad6d6297SScott Long 	case XPT_SCSI_IO: {
1453ad6d6297SScott Long 			struct CommandControlBlock *srb;
1454ad6d6297SScott Long 			int target=pccb->ccb_h.target_id;
1455f1c579b1SScott Long 
1456ad6d6297SScott Long 			if(target == 16) {
1457ad6d6297SScott Long 				/* virtual device for iop message transfer */
1458ad6d6297SScott Long 				arcmsr_handle_virtual_command(acb, pccb);
1459ad6d6297SScott Long 				return;
1460ad6d6297SScott Long 			}
1461ad6d6297SScott Long  			if((srb=arcmsr_get_freesrb(acb)) == NULL) {
1462ad6d6297SScott Long 				pccb->ccb_h.status |= CAM_RESRC_UNAVAIL;
1463f1c579b1SScott Long 				xpt_done(pccb);
1464f1c579b1SScott Long 				return;
1465f1c579b1SScott Long 			}
1466ad6d6297SScott Long  			pccb->ccb_h.arcmsr_ccbsrb_ptr=srb;
1467ad6d6297SScott Long 			pccb->ccb_h.arcmsr_ccbacb_ptr=acb;
1468ad6d6297SScott Long 			srb->pccb=pccb;
1469ad6d6297SScott Long 			if((pccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
1470ad6d6297SScott Long 				if(!(pccb->ccb_h.flags & CAM_SCATTER_VALID)) {
1471ad6d6297SScott Long 					/* Single buffer */
1472ad6d6297SScott Long 					if(!(pccb->ccb_h.flags & CAM_DATA_PHYS)) {
1473ad6d6297SScott Long 						/* Buffer is virtual */
1474ad6d6297SScott Long 						u_int32_t error, s;
1475f1c579b1SScott Long 
1476f1c579b1SScott Long 						s=splsoftvm();
1477ad6d6297SScott Long 						error =	bus_dmamap_load(acb->dm_segs_dmat
1478ad6d6297SScott Long 							, srb->dm_segs_dmamap
1479ad6d6297SScott Long 							, pccb->csio.data_ptr
1480ad6d6297SScott Long 							, pccb->csio.dxfer_len
1481ad6d6297SScott Long 							, arcmsr_executesrb, srb, /*flags*/0);
1482ad6d6297SScott Long 	         				if(error == EINPROGRESS) {
1483ad6d6297SScott Long 							xpt_freeze_simq(acb->psim, 1);
1484f1c579b1SScott Long 							pccb->ccb_h.status |= CAM_RELEASE_SIMQ;
1485f1c579b1SScott Long 						}
1486f1c579b1SScott Long 						splx(s);
1487ad6d6297SScott Long 					} else {
1488ad6d6297SScott Long 						/* Buffer is physical */
14891c7e9358SScott Long 						panic("arcmsr: CAM_DATA_PHYS not supported");
1490f1c579b1SScott Long 					}
1491ad6d6297SScott Long 				} else {
1492ad6d6297SScott Long 					/* Scatter/gather list */
1493f1c579b1SScott Long 					struct bus_dma_segment *segs;
1494f1c579b1SScott Long 
1495ad6d6297SScott Long 					if((pccb->ccb_h.flags & CAM_SG_LIST_PHYS) == 0
1496ad6d6297SScott Long 					|| (pccb->ccb_h.flags & CAM_DATA_PHYS) != 0) {
1497ad6d6297SScott Long 						pccb->ccb_h.status |= CAM_PROVIDE_FAIL;
1498f1c579b1SScott Long 						xpt_done(pccb);
1499ad6d6297SScott Long 						free(srb, M_DEVBUF);
1500f1c579b1SScott Long 						return;
1501f1c579b1SScott Long 					}
1502f1c579b1SScott Long 					segs=(struct bus_dma_segment *)pccb->csio.data_ptr;
1503ad6d6297SScott Long 					arcmsr_executesrb(srb, segs, pccb->csio.sglist_cnt, 0);
1504f1c579b1SScott Long 				}
1505ad6d6297SScott Long 			} else {
1506ad6d6297SScott Long 				arcmsr_executesrb(srb, NULL, 0, 0);
1507f1c579b1SScott Long 			}
1508f1c579b1SScott Long 			break;
1509f1c579b1SScott Long 		}
1510ad6d6297SScott Long 	case XPT_TARGET_IO: {
1511ad6d6297SScott Long 			/* target mode not yet support vendor specific commands. */
1512ad6d6297SScott Long 			pccb->ccb_h.status |= CAM_REQ_CMP;
1513f1c579b1SScott Long 			xpt_done(pccb);
1514f1c579b1SScott Long 			break;
1515f1c579b1SScott Long 		}
1516ad6d6297SScott Long 	case XPT_PATH_INQ: {
1517f1c579b1SScott Long 			struct ccb_pathinq *cpi= &pccb->cpi;
1518f1c579b1SScott Long 
1519f1c579b1SScott Long 			cpi->version_num=1;
1520f1c579b1SScott Long 			cpi->hba_inquiry=PI_SDTR_ABLE | PI_TAG_ABLE;
1521f1c579b1SScott Long 			cpi->target_sprt=0;
1522f1c579b1SScott Long 			cpi->hba_misc=0;
1523f1c579b1SScott Long 			cpi->hba_eng_cnt=0;
1524ad6d6297SScott Long 			cpi->max_target=ARCMSR_MAX_TARGETID;        /* 0-16 */
1525ad6d6297SScott Long 			cpi->max_lun=ARCMSR_MAX_TARGETLUN;	    /* 0-7 */
1526ad6d6297SScott Long 			cpi->initiator_id=ARCMSR_SCSI_INITIATOR_ID; /* 255 */
1527f1c579b1SScott Long 			cpi->bus_id=cam_sim_bus(psim);
1528f1c579b1SScott Long 			strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
1529f1c579b1SScott Long 			strncpy(cpi->hba_vid, "ARCMSR", HBA_IDLEN);
1530f1c579b1SScott Long 			strncpy(cpi->dev_name, cam_sim_name(psim), DEV_IDLEN);
1531f1c579b1SScott Long 			cpi->unit_number=cam_sim_unit(psim);
1532fa9ed865SMatt Jacob 			cpi->transport = XPORT_SPI;
1533fa9ed865SMatt Jacob 			cpi->transport_version = 2;
1534fa9ed865SMatt Jacob 			cpi->protocol = PROTO_SCSI;
1535fa9ed865SMatt Jacob 			cpi->protocol_version = SCSI_REV_2;
1536ad6d6297SScott Long 			cpi->ccb_h.status |= CAM_REQ_CMP;
1537f1c579b1SScott Long 			xpt_done(pccb);
1538f1c579b1SScott Long 			break;
1539f1c579b1SScott Long 		}
1540ad6d6297SScott Long 	case XPT_ABORT: {
1541f1c579b1SScott Long 			union ccb *pabort_ccb;
1542f1c579b1SScott Long 
1543f1c579b1SScott Long 			pabort_ccb=pccb->cab.abort_ccb;
1544ad6d6297SScott Long 			switch (pabort_ccb->ccb_h.func_code) {
1545f1c579b1SScott Long 			case XPT_ACCEPT_TARGET_IO:
1546f1c579b1SScott Long 			case XPT_IMMED_NOTIFY:
1547f1c579b1SScott Long 			case XPT_CONT_TARGET_IO:
1548ad6d6297SScott Long 				if(arcmsr_seek_cmd2abort(pabort_ccb)==TRUE) {
1549ad6d6297SScott Long 					pabort_ccb->ccb_h.status |= CAM_REQ_ABORTED;
1550f1c579b1SScott Long 					xpt_done(pabort_ccb);
1551ad6d6297SScott Long 					pccb->ccb_h.status |= CAM_REQ_CMP;
1552ad6d6297SScott Long 				} else {
1553f1c579b1SScott Long 					xpt_print_path(pabort_ccb->ccb_h.path);
1554f1c579b1SScott Long 					printf("Not found\n");
1555ad6d6297SScott Long 					pccb->ccb_h.status |= CAM_PATH_INVALID;
1556f1c579b1SScott Long 				}
1557f1c579b1SScott Long 				break;
1558f1c579b1SScott Long 			case XPT_SCSI_IO:
1559ad6d6297SScott Long 				pccb->ccb_h.status |= CAM_UA_ABORT;
1560f1c579b1SScott Long 				break;
1561f1c579b1SScott Long 			default:
1562ad6d6297SScott Long 				pccb->ccb_h.status |= CAM_REQ_INVALID;
1563f1c579b1SScott Long 				break;
1564f1c579b1SScott Long 			}
1565f1c579b1SScott Long 			xpt_done(pccb);
1566f1c579b1SScott Long 			break;
1567f1c579b1SScott Long 		}
1568f1c579b1SScott Long 	case XPT_RESET_BUS:
1569ad6d6297SScott Long 	case XPT_RESET_DEV: {
1570ad6d6297SScott Long 			u_int32_t     i;
1571f1c579b1SScott Long 
1572ad6d6297SScott Long 			arcmsr_bus_reset(acb);
1573ad6d6297SScott Long 			for (i=0; i < 500; i++) {
1574f1c579b1SScott Long 				DELAY(1000);
1575f1c579b1SScott Long 			}
1576ad6d6297SScott Long 			pccb->ccb_h.status |= CAM_REQ_CMP;
1577f1c579b1SScott Long 			xpt_done(pccb);
1578f1c579b1SScott Long 			break;
1579f1c579b1SScott Long 		}
1580ad6d6297SScott Long 	case XPT_TERM_IO: {
1581ad6d6297SScott Long 			pccb->ccb_h.status |= CAM_REQ_INVALID;
1582f1c579b1SScott Long 			xpt_done(pccb);
1583f1c579b1SScott Long 			break;
1584f1c579b1SScott Long 		}
1585ad6d6297SScott Long 	case XPT_GET_TRAN_SETTINGS: {
1586ad6d6297SScott Long 			struct ccb_trans_settings *cts;
1587ad6d6297SScott Long 			struct ccb_trans_settings_scsi *scsi;
1588ad6d6297SScott Long 			struct ccb_trans_settings_spi *spi;
1589ad6d6297SScott Long 
1590ad6d6297SScott Long 			if(pccb->ccb_h.target_id == 16) {
1591ad6d6297SScott Long 				pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL;
1592ad6d6297SScott Long 				xpt_done(pccb);
1593ad6d6297SScott Long 				break;
1594ad6d6297SScott Long 			}
1595ad6d6297SScott Long 
1596ad6d6297SScott Long 			cts= &pccb->cts;
1597ad6d6297SScott Long 			scsi = &cts->proto_specific.scsi;
1598ad6d6297SScott Long 			spi = &cts->xport_specific.spi;
1599fa9ed865SMatt Jacob 
1600fa9ed865SMatt Jacob 			cts->protocol = PROTO_SCSI;
1601fa9ed865SMatt Jacob 			cts->protocol_version = SCSI_REV_2;
1602fa9ed865SMatt Jacob 			cts->transport = XPORT_SPI;
1603fa9ed865SMatt Jacob 			cts->transport_version = 2;
1604fa9ed865SMatt Jacob 			spi->flags = CTS_SPI_FLAGS_DISC_ENB;
1605fa9ed865SMatt Jacob 			spi->sync_period=3;
1606fa9ed865SMatt Jacob 			spi->sync_offset=32;
1607fa9ed865SMatt Jacob 			spi->bus_width=MSG_EXT_WDTR_BUS_16_BIT;
1608fa9ed865SMatt Jacob 			scsi->flags = CTS_SCSI_FLAGS_TAG_ENB;
1609fa9ed865SMatt Jacob 			spi->valid = CTS_SPI_VALID_SYNC_RATE
1610fa9ed865SMatt Jacob 				| CTS_SPI_VALID_SYNC_OFFSET
1611fa9ed865SMatt Jacob 				| CTS_SPI_VALID_BUS_WIDTH;
1612fa9ed865SMatt Jacob 			scsi->valid = CTS_SCSI_VALID_TQ;
1613f1c579b1SScott Long 
1614ad6d6297SScott Long 			pccb->ccb_h.status |= CAM_REQ_CMP;
1615ad6d6297SScott Long 			xpt_done(pccb);
1616ad6d6297SScott Long 			break;
1617ad6d6297SScott Long 		}
1618ad6d6297SScott Long 	case XPT_SET_TRAN_SETTINGS: {
1619ad6d6297SScott Long 			pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL;
1620ad6d6297SScott Long 			xpt_done(pccb);
1621ad6d6297SScott Long 			break;
1622ad6d6297SScott Long 		}
1623ad6d6297SScott Long 	case XPT_CALC_GEOMETRY: {
1624ad6d6297SScott Long 			struct ccb_calc_geometry *ccg;
1625ad6d6297SScott Long 			u_int32_t size_mb;
1626ad6d6297SScott Long 			u_int32_t secs_per_cylinder;
1627ad6d6297SScott Long 
1628ad6d6297SScott Long 			if(pccb->ccb_h.target_id == 16) {
1629ad6d6297SScott Long 				pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL;
1630ad6d6297SScott Long 				xpt_done(pccb);
1631ad6d6297SScott Long 				break;
1632ad6d6297SScott Long 			}
1633f1c579b1SScott Long  			ccg= &pccb->ccg;
1634ad6d6297SScott Long 			if (ccg->block_size == 0) {
1635ad6d6297SScott Long 				pccb->ccb_h.status = CAM_REQ_INVALID;
1636ad6d6297SScott Long 				xpt_done(pccb);
1637ad6d6297SScott Long 				break;
1638ad6d6297SScott Long 			}
1639ad6d6297SScott Long 			if(((1024L * 1024L)/ccg->block_size) < 0) {
1640ad6d6297SScott Long 				pccb->ccb_h.status = CAM_REQ_INVALID;
1641ad6d6297SScott Long 				xpt_done(pccb);
1642ad6d6297SScott Long 				break;
1643ad6d6297SScott Long 			}
1644f1c579b1SScott Long 			size_mb=ccg->volume_size/((1024L * 1024L)/ccg->block_size);
1645ad6d6297SScott Long 			if(size_mb > 1024 ) {
1646f1c579b1SScott Long 				ccg->heads=255;
1647f1c579b1SScott Long 				ccg->secs_per_track=63;
1648ad6d6297SScott Long 			} else {
1649f1c579b1SScott Long 				ccg->heads=64;
1650f1c579b1SScott Long 				ccg->secs_per_track=32;
1651f1c579b1SScott Long 			}
1652f1c579b1SScott Long 			secs_per_cylinder=ccg->heads * ccg->secs_per_track;
1653f1c579b1SScott Long 			ccg->cylinders=ccg->volume_size / secs_per_cylinder;
1654ad6d6297SScott Long 			pccb->ccb_h.status |= CAM_REQ_CMP;
1655f1c579b1SScott Long 			xpt_done(pccb);
1656f1c579b1SScott Long 			break;
1657f1c579b1SScott Long 		}
1658f1c579b1SScott Long 	default:
1659ad6d6297SScott Long 		pccb->ccb_h.status |= CAM_REQ_INVALID;
1660f1c579b1SScott Long 		xpt_done(pccb);
1661f1c579b1SScott Long 		break;
1662f1c579b1SScott Long 	}
1663f1c579b1SScott Long 	return;
1664f1c579b1SScott Long }
1665f1c579b1SScott Long /*
1666f1c579b1SScott Long **********************************************************************
1667f1c579b1SScott Long **********************************************************************
1668f1c579b1SScott Long */
1669ad6d6297SScott Long static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb)
1670f1c579b1SScott Long {
1671ad6d6297SScott Long 	acb->acb_flags |= ACB_F_MSG_START_BGRB;
1672ad6d6297SScott Long 	CHIP_REG_WRITE32(inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB);
1673ad6d6297SScott Long 	if(arcmsr_wait_msgint_ready(acb)) {
1674ad6d6297SScott Long 		printf("arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit);
1675ad6d6297SScott Long 	}
1676f1c579b1SScott Long 	return;
1677f1c579b1SScott Long }
1678f1c579b1SScott Long /*
1679f1c579b1SScott Long **********************************************************************
1680f1c579b1SScott Long **********************************************************************
1681f1c579b1SScott Long */
1682ad6d6297SScott Long static void arcmsr_polling_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb)
1683f1c579b1SScott Long {
1684ad6d6297SScott Long 	struct CommandControlBlock *srb;
1685ad6d6297SScott Long 	uint32_t flag_srb, outbound_intstatus, poll_srb_done=0, poll_count=0;
1686ad6d6297SScott Long 	int id, lun;
1687f1c579b1SScott Long 
1688ad6d6297SScott Long polling_srb_retry:
1689ad6d6297SScott Long 	poll_count++;
1690ad6d6297SScott Long 	outbound_intstatus=CHIP_REG_READ32(outbound_intstatus) & acb->outbound_int_enable;
1691ad6d6297SScott Long 	CHIP_REG_WRITE32(outbound_intstatus, outbound_intstatus);/*clear interrupt*/
1692ad6d6297SScott Long 	while(1) {
1693ad6d6297SScott Long 		if((flag_srb=CHIP_REG_READ32(outbound_queueport))==0xFFFFFFFF) {
1694ad6d6297SScott Long 			if(poll_srb_done) {
1695ad6d6297SScott Long 				break;/*chip FIFO no ccb for completion already*/
1696ad6d6297SScott Long 			} else {
1697ad6d6297SScott Long 				UDELAY(25000);
1698ad6d6297SScott Long 				if(poll_count > 100) {
1699ad6d6297SScott Long 					break;
1700f1c579b1SScott Long 				}
1701ad6d6297SScott Long 				goto polling_srb_retry;
1702f1c579b1SScott Long 			}
1703ad6d6297SScott Long 		}
1704ad6d6297SScott Long 		/* check ifcommand done with no error*/
1705ad6d6297SScott Long 		srb=(struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb << 5));
1706ad6d6297SScott Long 		/*frame must be 32 bytes aligned*/
1707ad6d6297SScott Long 		if((srb->acb!=acb) || (srb->startdone!=ARCMSR_SRB_START)) {
1708ad6d6297SScott Long 			if((srb->startdone==ARCMSR_SRB_ABORTED) && (srb==poll_srb)) {
1709ad6d6297SScott Long 				printf("arcmsr%d: scsi id=%d lun=%d srb='%p'"
1710ad6d6297SScott Long 					"poll command abort successfully \n"
1711ad6d6297SScott Long 					, acb->pci_unit
1712ad6d6297SScott Long 					, srb->pccb->ccb_h.target_id
1713ad6d6297SScott Long 					, srb->pccb->ccb_h.target_lun, srb);
1714ad6d6297SScott Long 				srb->pccb->ccb_h.status |= CAM_REQ_ABORTED;
1715ad6d6297SScott Long 				arcmsr_srb_complete(srb, 1);
1716ad6d6297SScott Long 				poll_srb_done=1;
1717ad6d6297SScott Long 				continue;
1718ad6d6297SScott Long 			}
1719ad6d6297SScott Long 			printf("arcmsr%d: polling get an illegal srb command done srb='%p'"
1720ad6d6297SScott Long 				"srboutstandingcount=%d \n"
1721ad6d6297SScott Long 				, acb->pci_unit
1722ad6d6297SScott Long 				, srb, acb->srboutstandingcount);
1723ad6d6297SScott Long 			continue;
1724ad6d6297SScott Long 		}
1725ad6d6297SScott Long 		id=srb->pccb->ccb_h.target_id;
1726ad6d6297SScott Long 		lun=srb->pccb->ccb_h.target_lun;
1727ad6d6297SScott Long 		if((flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR)==0) {
1728ad6d6297SScott Long 			if(acb->devstate[id][lun]==ARECA_RAID_GONE) {
1729ad6d6297SScott Long                 acb->devstate[id][lun]=ARECA_RAID_GOOD;
1730ad6d6297SScott Long 			}
1731ad6d6297SScott Long  			srb->pccb->ccb_h.status |= CAM_REQ_CMP;
1732ad6d6297SScott Long 			arcmsr_srb_complete(srb, 1);
1733ad6d6297SScott Long 		} else {
1734ad6d6297SScott Long 			switch(srb->arcmsr_cdb.DeviceStatus) {
1735ad6d6297SScott Long 			case ARCMSR_DEV_SELECT_TIMEOUT: {
1736ad6d6297SScott Long 					acb->devstate[id][lun]=ARECA_RAID_GONE;
1737ad6d6297SScott Long 					srb->pccb->ccb_h.status |= CAM_SEL_TIMEOUT;
1738ad6d6297SScott Long 					arcmsr_srb_complete(srb, 1);
1739ad6d6297SScott Long 				}
1740ad6d6297SScott Long 				break;
1741ad6d6297SScott Long 			case ARCMSR_DEV_ABORTED:
1742ad6d6297SScott Long 			case ARCMSR_DEV_INIT_FAIL: {
1743ad6d6297SScott Long 					acb->devstate[id][lun]=ARECA_RAID_GONE;
1744ad6d6297SScott Long 					srb->pccb->ccb_h.status |= CAM_DEV_NOT_THERE;
1745ad6d6297SScott Long 					arcmsr_srb_complete(srb, 1);
1746ad6d6297SScott Long 				}
1747ad6d6297SScott Long 				break;
1748ad6d6297SScott Long 			case SCSISTAT_CHECK_CONDITION: {
1749ad6d6297SScott Long 					acb->devstate[id][lun]=ARECA_RAID_GOOD;
1750ad6d6297SScott Long 					arcmsr_report_sense_info(srb);
1751ad6d6297SScott Long 					arcmsr_srb_complete(srb, 1);
1752ad6d6297SScott Long 				}
1753ad6d6297SScott Long 				break;
1754ad6d6297SScott Long 			default:
1755ad6d6297SScott Long 				printf("arcmsr%d: scsi id=%d lun=%d"
1756ad6d6297SScott Long 					"polling and getting command error done"
1757ad6d6297SScott Long 					", but got unknow DeviceStatus=0x%x \n"
1758ad6d6297SScott Long 					, acb->pci_unit, id, lun, srb->arcmsr_cdb.DeviceStatus);
1759ad6d6297SScott Long 				acb->devstate[id][lun]=ARECA_RAID_GONE;
1760ad6d6297SScott Long 				srb->pccb->ccb_h.status |= CAM_UNCOR_PARITY;
1761ad6d6297SScott Long 				/*unknow error or crc error just for retry*/
1762ad6d6297SScott Long 				arcmsr_srb_complete(srb, 1);
1763ad6d6297SScott Long 				break;
1764ad6d6297SScott Long 			}
1765ad6d6297SScott Long 		}
1766ad6d6297SScott Long 	}	/*drain reply FIFO*/
1767f1c579b1SScott Long 	return;
1768f1c579b1SScott Long }
1769f1c579b1SScott Long /*
1770f1c579b1SScott Long **********************************************************************
1771ad6d6297SScott Long **  get firmware miscellaneous data
1772ad6d6297SScott Long **********************************************************************
1773ad6d6297SScott Long */
1774ad6d6297SScott Long static void arcmsr_get_firmware_spec(struct AdapterControlBlock *acb)
1775ad6d6297SScott Long {
1776ad6d6297SScott Long 	char *acb_firm_model=acb->firm_model;
1777ad6d6297SScott Long 	char *acb_firm_version=acb->firm_version;
1778ad6d6297SScott Long 	size_t iop_firm_model=offsetof(struct MessageUnit,message_rwbuffer[15]);   /*firm_model,15,60-67*/
1779ad6d6297SScott Long 	size_t iop_firm_version=offsetof(struct MessageUnit,message_rwbuffer[17]); /*firm_version,17,68-83*/
1780ad6d6297SScott Long 	int i;
1781ad6d6297SScott Long 
1782ad6d6297SScott Long 	CHIP_REG_WRITE32(inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG);
1783ad6d6297SScott Long 	if(arcmsr_wait_msgint_ready(acb)) {
1784ad6d6297SScott Long 		printf("arcmsr%d: wait 'get adapter firmware miscellaneous data' timeout \n"
1785ad6d6297SScott Long 			, acb->pci_unit);
1786ad6d6297SScott Long 	}
1787ad6d6297SScott Long 	i=0;
1788ad6d6297SScott Long 	while(i<8) {
1789ad6d6297SScott Long 		*acb_firm_model=bus_space_read_1(acb->btag, acb->bhandle, iop_firm_model+i);
1790ad6d6297SScott Long 		/* 8 bytes firm_model, 15, 60-67*/
1791ad6d6297SScott Long 		acb_firm_model++;
1792ad6d6297SScott Long 		i++;
1793ad6d6297SScott Long 	}
1794ad6d6297SScott Long 	i=0;
1795ad6d6297SScott Long 	while(i<16) {
1796ad6d6297SScott Long 		*acb_firm_version=bus_space_read_1(acb->btag, acb->bhandle, iop_firm_version+i);
1797ad6d6297SScott Long 		/* 16 bytes firm_version, 17, 68-83*/
1798ad6d6297SScott Long 		acb_firm_version++;
1799ad6d6297SScott Long 		i++;
1800ad6d6297SScott Long 	}
1801ad6d6297SScott Long 	printf("ARECA RAID ADAPTER%d: %s \n", acb->pci_unit, ARCMSR_DRIVER_VERSION);
1802ad6d6297SScott Long 	printf("ARECA RAID ADAPTER%d: FIRMWARE VERSION %s \n", acb->pci_unit, acb->firm_version);
1803ad6d6297SScott Long 	acb->firm_request_len=CHIP_REG_READ32(message_rwbuffer[1]);   /*firm_request_len, 1, 04-07*/
1804ad6d6297SScott Long 	acb->firm_numbers_queue=CHIP_REG_READ32(message_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/
1805ad6d6297SScott Long 	acb->firm_sdram_size=CHIP_REG_READ32(message_rwbuffer[3]);    /*firm_sdram_size, 3, 12-15*/
1806ad6d6297SScott Long 	acb->firm_ide_channels=CHIP_REG_READ32(message_rwbuffer[4]);  /*firm_ide_channels, 4, 16-19*/
1807ad6d6297SScott Long 	return;
1808ad6d6297SScott Long }
1809ad6d6297SScott Long /*
1810ad6d6297SScott Long **********************************************************************
1811ad6d6297SScott Long **  start background rebulid
1812ad6d6297SScott Long **********************************************************************
1813ad6d6297SScott Long */
1814ad6d6297SScott Long static void arcmsr_iop_init(struct AdapterControlBlock *acb)
1815ad6d6297SScott Long {
1816ad6d6297SScott Long 	u_int32_t intmask_org, mask, outbound_doorbell, firmware_state=0;
1817ad6d6297SScott Long 
1818ad6d6297SScott Long 	do {
1819ad6d6297SScott Long         	firmware_state=CHIP_REG_READ32(outbound_msgaddr1);
1820ad6d6297SScott Long 	} while((firmware_state & ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK)==0);
1821ad6d6297SScott Long 	intmask_org=CHIP_REG_READ32(outbound_intmask)|ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE;
1822ad6d6297SScott Long 	CHIP_REG_WRITE32(outbound_intmask, intmask_org);
1823ad6d6297SScott Long 	intmask_org=CHIP_REG_READ32(outbound_intmask)|ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE;
1824ad6d6297SScott Long 	arcmsr_get_firmware_spec(acb);
1825ad6d6297SScott Long 	arcmsr_start_adapter_bgrb(acb);
1826ad6d6297SScott Long 	/* clear Qbuffer if door bell ringed */
1827ad6d6297SScott Long 	outbound_doorbell=CHIP_REG_READ32(outbound_doorbell);
1828ad6d6297SScott Long 	CHIP_REG_WRITE32(outbound_doorbell, outbound_doorbell);/*clear interrupt */
1829ad6d6297SScott Long 	CHIP_REG_WRITE32(inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK);
1830ad6d6297SScott Long 	/* enable outbound Post Queue, outbound message0, outbell doorbell Interrupt */
1831ad6d6297SScott Long 	mask=~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE|ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE);
1832ad6d6297SScott Long 	CHIP_REG_WRITE32(outbound_intmask, intmask_org & mask);
1833ad6d6297SScott Long 	acb->outbound_int_enable = ~(intmask_org & mask) & 0x000000ff;
1834ad6d6297SScott Long 	acb->acb_flags |=ACB_F_IOP_INITED;
1835ad6d6297SScott Long 	return;
1836ad6d6297SScott Long }
1837ad6d6297SScott Long /*
1838ad6d6297SScott Long **********************************************************************
1839f1c579b1SScott Long **********************************************************************
1840f1c579b1SScott Long */
1841f1c579b1SScott Long static void arcmsr_map_freesrb(void *arg, bus_dma_segment_t *segs, int nseg, int error)
1842f1c579b1SScott Long {
1843ad6d6297SScott Long 	struct AdapterControlBlock *acb=arg;
1844ad6d6297SScott Long 	struct CommandControlBlock *srb_tmp;
1845ad6d6297SScott Long 	u_int8_t * dma_memptr;
1846ad6d6297SScott Long 	u_int32_t i, srb_phyaddr_hi32;
1847ad6d6297SScott Long 	unsigned long srb_phyaddr=(unsigned long)segs->ds_addr;
1848f1c579b1SScott Long 
1849ad6d6297SScott Long 	dma_memptr=acb->uncacheptr;
1850ad6d6297SScott Long 	srb_phyaddr=segs->ds_addr; /* We suppose bus_addr_t high part always 0 here*/
1851ad6d6297SScott Long 	if(((unsigned long)dma_memptr & 0x1F)!=0) {
1852ad6d6297SScott Long 		dma_memptr=dma_memptr+(0x20-((unsigned long)dma_memptr & 0x1F));
1853ad6d6297SScott Long 		srb_phyaddr=srb_phyaddr+(0x20-((unsigned long)srb_phyaddr & 0x1F));
1854f1c579b1SScott Long 	}
1855ad6d6297SScott Long 	srb_tmp=(struct CommandControlBlock *)dma_memptr;
1856ad6d6297SScott Long 	for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++) {
1857ad6d6297SScott Long 		/*srb address must 32 (0x20) boundary*/
1858ad6d6297SScott Long 		if(((unsigned long)srb_tmp & 0x1F)==0) {
1859ad6d6297SScott Long 			if(bus_dmamap_create(acb->dm_segs_dmat, /*flags*/0, &srb_tmp->dm_segs_dmamap)!=0) {
1860ad6d6297SScott Long 				acb->acb_flags |= ACB_F_MAPFREESRB_FAILD;
1861ad6d6297SScott Long 				printf("arcmsr%d: srb dmamap bus_dmamap_create error\n", acb->pci_unit);
1862ad6d6297SScott Long 				return;
1863ad6d6297SScott Long 			}
1864ad6d6297SScott Long 			srb_tmp->cdb_shifted_phyaddr=srb_phyaddr >> 5;
1865ad6d6297SScott Long 			srb_tmp->acb=acb;
1866ad6d6297SScott Long 			acb->srbworkingQ[i]=acb->psrb_pool[i]=srb_tmp;
1867ad6d6297SScott Long 			srb_phyaddr=srb_phyaddr+sizeof(struct CommandControlBlock);
1868ad6d6297SScott Long 		} else {
1869ad6d6297SScott Long 			acb->acb_flags |= ACB_F_MAPFREESRB_FAILD;
1870ad6d6297SScott Long 			printf("arcmsr%d: dma_memptr=%p i=%d"
1871ad6d6297SScott Long 				"this srb cross 32 bytes boundary ignored srb_tmp=%p \n"
1872ad6d6297SScott Long 				, acb->pci_unit, dma_memptr, i, srb_tmp);
1873ad6d6297SScott Long 			return;
1874ad6d6297SScott Long 		}
1875ad6d6297SScott Long 		srb_tmp++;
1876ad6d6297SScott Long 	}
1877ad6d6297SScott Long 	acb->vir2phy_offset=(unsigned long)srb_tmp-(unsigned long)srb_phyaddr;
1878f1c579b1SScott Long 	/*
1879f1c579b1SScott Long 	********************************************************************
1880f1c579b1SScott Long 	** here we need to tell iop 331 our freesrb.HighPart
1881f1c579b1SScott Long 	** if freesrb.HighPart is not zero
1882f1c579b1SScott Long 	********************************************************************
1883f1c579b1SScott Long 	*/
1884ad6d6297SScott Long 	srb_phyaddr_hi32=(uint32_t) ((srb_phyaddr>>16)>>16);
1885ad6d6297SScott Long 	if(srb_phyaddr_hi32!=0) {
1886ad6d6297SScott Long 		CHIP_REG_WRITE32(message_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG);
1887ad6d6297SScott Long 		CHIP_REG_WRITE32(message_rwbuffer[1], srb_phyaddr_hi32);
1888ad6d6297SScott Long 		CHIP_REG_WRITE32(inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG);
1889ad6d6297SScott Long 		if(arcmsr_wait_msgint_ready(acb)) {
1890ad6d6297SScott Long 			printf("arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit);
1891f1c579b1SScott Long 		}
1892f1c579b1SScott Long 	}
1893f1c579b1SScott Long 	return;
1894f1c579b1SScott Long }
1895f1c579b1SScott Long /*
1896f1c579b1SScott Long ************************************************************************
1897f1c579b1SScott Long **
1898f1c579b1SScott Long **
1899f1c579b1SScott Long ************************************************************************
1900f1c579b1SScott Long */
1901ad6d6297SScott Long static void arcmsr_free_resource(struct AdapterControlBlock *acb)
1902f1c579b1SScott Long {
1903f1c579b1SScott Long 	/* remove the control device */
1904ad6d6297SScott Long 	if(acb->ioctl_dev != NULL) {
1905ad6d6297SScott Long 		destroy_dev(acb->ioctl_dev);
1906f1c579b1SScott Long 	}
1907ad6d6297SScott Long 	bus_dmamap_unload(acb->srb_dmat, acb->srb_dmamap);
1908ad6d6297SScott Long 	bus_dmamap_destroy(acb->srb_dmat, acb->srb_dmamap);
1909ad6d6297SScott Long 	bus_dma_tag_destroy(acb->srb_dmat);
1910ad6d6297SScott Long 	bus_dma_tag_destroy(acb->dm_segs_dmat);
1911ad6d6297SScott Long 	bus_dma_tag_destroy(acb->parent_dmat);
1912f1c579b1SScott Long 	return;
1913f1c579b1SScott Long }
1914f1c579b1SScott Long /*
1915f1c579b1SScott Long ************************************************************************
1916f1c579b1SScott Long ************************************************************************
1917f1c579b1SScott Long */
1918ad6d6297SScott Long static u_int32_t arcmsr_initialize(device_t dev)
1919f1c579b1SScott Long {
1920ad6d6297SScott Long 	struct AdapterControlBlock *acb=device_get_softc(dev);
1921ad6d6297SScott Long 	u_int32_t intmask_org, rid=PCIR_BAR(0);
1922f1c579b1SScott Long 	vm_offset_t	mem_base;
1923ad6d6297SScott Long 	u_int16_t pci_command;
1924ad6d6297SScott Long 	int i, j;
1925f1c579b1SScott Long 
1926f1c579b1SScott Long #if __FreeBSD_version >= 502010
1927f1c579b1SScott Long 	if(bus_dma_tag_create(  /*parent*/	NULL,
1928f1c579b1SScott Long 				/*alignemnt*/	1,
1929f1c579b1SScott Long 				/*boundary*/	0,
1930701d9f1fSScott Long 				/*lowaddr*/	BUS_SPACE_MAXADDR,
1931f1c579b1SScott Long 				/*highaddr*/	BUS_SPACE_MAXADDR,
1932f1c579b1SScott Long 				/*filter*/	NULL,
1933f1c579b1SScott Long 				/*filterarg*/	NULL,
1934f1c579b1SScott Long 				/*maxsize*/	BUS_SPACE_MAXSIZE_32BIT,
1935f1c579b1SScott Long 				/*nsegments*/	BUS_SPACE_UNRESTRICTED,
1936f1c579b1SScott Long 				/*maxsegsz*/	BUS_SPACE_MAXSIZE_32BIT,
1937f1c579b1SScott Long 				/*flags*/	0,
1938f1c579b1SScott Long 				/*lockfunc*/	NULL,
1939f1c579b1SScott Long 				/*lockarg*/	NULL,
1940ad6d6297SScott Long 						&acb->parent_dmat) != 0)
1941f1c579b1SScott Long #else
1942f1c579b1SScott Long 	if(bus_dma_tag_create(  /*parent*/	NULL,
1943f1c579b1SScott Long 				/*alignemnt*/	1,
1944f1c579b1SScott Long 				/*boundary*/	0,
1945701d9f1fSScott Long 				/*lowaddr*/	BUS_SPACE_MAXADDR,
1946f1c579b1SScott Long 				/*highaddr*/	BUS_SPACE_MAXADDR,
1947f1c579b1SScott Long 				/*filter*/	NULL,
1948f1c579b1SScott Long 				/*filterarg*/	NULL,
1949f1c579b1SScott Long 				/*maxsize*/	BUS_SPACE_MAXSIZE_32BIT,
1950f1c579b1SScott Long 				/*nsegments*/	BUS_SPACE_UNRESTRICTED,
1951f1c579b1SScott Long 				/*maxsegsz*/	BUS_SPACE_MAXSIZE_32BIT,
1952f1c579b1SScott Long 				/*flags*/	0,
1953ad6d6297SScott Long 						&acb->parent_dmat) != 0)
1954f1c579b1SScott Long #endif
1955f1c579b1SScott Long 	{
1956ad6d6297SScott Long 		printf("arcmsr%d: parent_dmat bus_dma_tag_create failure!\n", acb->pci_unit);
1957f1c579b1SScott Long 		return ENOMEM;
1958f1c579b1SScott Long 	}
1959f1c579b1SScott Long 	/* Create a single tag describing a region large enough to hold all of the s/g lists we will need. */
1960f1c579b1SScott Long #if __FreeBSD_version >= 502010
1961ad6d6297SScott Long 	if(bus_dma_tag_create(  /*parent_dmat*/	acb->parent_dmat,
1962f1c579b1SScott Long 				/*alignment*/	1,
1963f1c579b1SScott Long 				/*boundary*/	0,
1964f1c579b1SScott Long 				/*lowaddr*/	BUS_SPACE_MAXADDR,
1965f1c579b1SScott Long 				/*highaddr*/	BUS_SPACE_MAXADDR,
1966f1c579b1SScott Long 				/*filter*/	NULL,
1967f1c579b1SScott Long 				/*filterarg*/	NULL,
1968f1c579b1SScott Long 				/*maxsize*/	MAXBSIZE,
1969f1c579b1SScott Long 				/*nsegments*/	ARCMSR_MAX_SG_ENTRIES,
1970f1c579b1SScott Long 				/*maxsegsz*/	BUS_SPACE_MAXSIZE_32BIT,
1971ad6d6297SScott Long 				/*flags*/	0,
1972f1c579b1SScott Long 				/*lockfunc*/	busdma_lock_mutex,
1973f1c579b1SScott Long 				/*lockarg*/	&Giant,
1974ad6d6297SScott Long 						&acb->dm_segs_dmat) != 0)
1975f1c579b1SScott Long #else
1976ad6d6297SScott Long 	if(bus_dma_tag_create(  /*parent_dmat*/	acb->parent_dmat,
1977f1c579b1SScott Long 				/*alignment*/	1,
1978f1c579b1SScott Long 				/*boundary*/	0,
1979f1c579b1SScott Long 				/*lowaddr*/	BUS_SPACE_MAXADDR,
1980f1c579b1SScott Long 				/*highaddr*/	BUS_SPACE_MAXADDR,
1981f1c579b1SScott Long 				/*filter*/	NULL,
1982f1c579b1SScott Long 				/*filterarg*/	NULL,
1983f1c579b1SScott Long 				/*maxsize*/	MAXBSIZE,
1984f1c579b1SScott Long 				/*nsegments*/	ARCMSR_MAX_SG_ENTRIES,
1985f1c579b1SScott Long 				/*maxsegsz*/	BUS_SPACE_MAXSIZE_32BIT,
1986ad6d6297SScott Long 				/*flags*/	0,
1987ad6d6297SScott Long 						&acb->dm_segs_dmat) != 0)
1988f1c579b1SScott Long #endif
1989f1c579b1SScott Long 	{
1990ad6d6297SScott Long 		bus_dma_tag_destroy(acb->parent_dmat);
1991ad6d6297SScott Long 		printf("arcmsr%d: dm_segs_dmat bus_dma_tag_create failure!\n", acb->pci_unit);
1992f1c579b1SScott Long 		return ENOMEM;
1993f1c579b1SScott Long 	}
1994ad6d6297SScott Long 	/* DMA tag for our srb structures.... Allocate the freesrb memory */
1995f1c579b1SScott Long #if __FreeBSD_version >= 502010
1996ad6d6297SScott Long 	if(bus_dma_tag_create(  /*parent_dmat*/	acb->parent_dmat,
1997f1c579b1SScott Long 				/*alignment*/	1,
1998f1c579b1SScott Long 				/*boundary*/	0,
1999f1c579b1SScott Long 				/*lowaddr*/	BUS_SPACE_MAXADDR_32BIT,
2000f1c579b1SScott Long 				/*highaddr*/	BUS_SPACE_MAXADDR,
2001f1c579b1SScott Long 				/*filter*/	NULL,
2002f1c579b1SScott Long 				/*filterarg*/	NULL,
2003ad6d6297SScott Long 				/*maxsize*/	ARCMSR_SRBS_POOL_SIZE,
2004f1c579b1SScott Long 				/*nsegments*/	1,
2005f1c579b1SScott Long 				/*maxsegsz*/	BUS_SPACE_MAXSIZE_32BIT,
2006701d9f1fSScott Long 				/*flags*/	0,
2007f1c579b1SScott Long 				/*lockfunc*/	NULL,
2008f1c579b1SScott Long 				/*lockarg*/	NULL,
2009ad6d6297SScott Long 						&acb->srb_dmat) != 0)
2010f1c579b1SScott Long #else
2011ad6d6297SScott Long 	if(bus_dma_tag_create(  /*parent_dmat*/	acb->parent_dmat,
2012f1c579b1SScott Long 				/*alignment*/	1,
2013f1c579b1SScott Long 				/*boundary*/	0,
2014f1c579b1SScott Long 				/*lowaddr*/	BUS_SPACE_MAXADDR_32BIT,
2015f1c579b1SScott Long 				/*highaddr*/	BUS_SPACE_MAXADDR,
2016f1c579b1SScott Long 				/*filter*/	NULL,
2017f1c579b1SScott Long 				/*filterarg*/	NULL,
2018ad6d6297SScott Long 				/*maxsize*/	ARCMSR_SRBS_POOL_SIZE,
2019f1c579b1SScott Long 				/*nsegments*/	1,
2020f1c579b1SScott Long 				/*maxsegsz*/	BUS_SPACE_MAXSIZE_32BIT,
2021701d9f1fSScott Long 				/*flags*/	0,
2022ad6d6297SScott Long 						&acb->srb_dmat) != 0)
2023f1c579b1SScott Long #endif
2024f1c579b1SScott Long 	{
2025ad6d6297SScott Long 		bus_dma_tag_destroy(acb->dm_segs_dmat);
2026ad6d6297SScott Long 		bus_dma_tag_destroy(acb->parent_dmat);
2027ad6d6297SScott Long 		printf("arcmsr%d: srb_dmat bus_dma_tag_create failure!\n", acb->pci_unit);
2028f1c579b1SScott Long 		return ENXIO;
2029f1c579b1SScott Long 	}
2030f1c579b1SScott Long 	/* Allocation for our srbs */
2031ad6d6297SScott Long 	if(bus_dmamem_alloc(acb->srb_dmat, (void **)&acb->uncacheptr
2032ad6d6297SScott Long 		, BUS_DMA_WAITOK | BUS_DMA_COHERENT, &acb->srb_dmamap) != 0) {
2033ad6d6297SScott Long 		bus_dma_tag_destroy(acb->srb_dmat);
2034ad6d6297SScott Long 		bus_dma_tag_destroy(acb->dm_segs_dmat);
2035ad6d6297SScott Long 		bus_dma_tag_destroy(acb->parent_dmat);
2036ad6d6297SScott Long 		printf("arcmsr%d: srb_dmat bus_dmamem_alloc failure!\n", acb->pci_unit);
2037f1c579b1SScott Long 		return ENXIO;
2038f1c579b1SScott Long 	}
2039f1c579b1SScott Long 	/* And permanently map them */
2040ad6d6297SScott Long 	if(bus_dmamap_load(acb->srb_dmat, acb->srb_dmamap, acb->uncacheptr
2041ad6d6297SScott Long 		, ARCMSR_SRBS_POOL_SIZE, arcmsr_map_freesrb, acb, /*flags*/0)) {
2042ad6d6297SScott Long 		bus_dma_tag_destroy(acb->srb_dmat);
2043ad6d6297SScott Long 		bus_dma_tag_destroy(acb->dm_segs_dmat);
2044ad6d6297SScott Long 		bus_dma_tag_destroy(acb->parent_dmat);
2045ad6d6297SScott Long 		printf("arcmsr%d: srb_dmat bus_dmamap_load failure!\n", acb->pci_unit);
2046f1c579b1SScott Long 		return ENXIO;
2047f1c579b1SScott Long 	}
2048f1c579b1SScott Long 	pci_command=pci_read_config(dev, PCIR_COMMAND, 2);
2049f1c579b1SScott Long 	pci_command |= PCIM_CMD_BUSMASTEREN;
2050f1c579b1SScott Long 	pci_command |= PCIM_CMD_PERRESPEN;
2051f1c579b1SScott Long 	pci_command |= PCIM_CMD_MWRICEN;
2052f1c579b1SScott Long 	/* Enable Busmaster/Mem */
2053f1c579b1SScott Long 	pci_command |= PCIM_CMD_MEMEN;
2054f1c579b1SScott Long 	pci_write_config(dev, PCIR_COMMAND, pci_command, 2);
2055ad6d6297SScott Long 	acb->sys_res_arcmsr=bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 0ul, ~0ul, 0x1000, RF_ACTIVE);
2056ad6d6297SScott Long 	if(acb->sys_res_arcmsr == NULL) {
2057ad6d6297SScott Long 		arcmsr_free_resource(acb);
2058ad6d6297SScott Long 		printf("arcmsr%d: bus_alloc_resource failure!\n", acb->pci_unit);
2059f1c579b1SScott Long 		return ENOMEM;
2060f1c579b1SScott Long 	}
2061ad6d6297SScott Long 	if(rman_get_start(acb->sys_res_arcmsr) <= 0) {
2062ad6d6297SScott Long 		arcmsr_free_resource(acb);
2063ad6d6297SScott Long 		printf("arcmsr%d: rman_get_start failure!\n", acb->pci_unit);
2064f1c579b1SScott Long 		return ENXIO;
2065f1c579b1SScott Long 	}
2066ad6d6297SScott Long 	mem_base=(vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr);
2067ad6d6297SScott Long 	if(mem_base==0) {
2068ad6d6297SScott Long 		arcmsr_free_resource(acb);
2069ad6d6297SScott Long 		printf("arcmsr%d: rman_get_virtual failure!\n", acb->pci_unit);
2070f1c579b1SScott Long 		return ENXIO;
2071f1c579b1SScott Long 	}
2072ad6d6297SScott Long 	if(acb->acb_flags & ACB_F_MAPFREESRB_FAILD) {
2073ad6d6297SScott Long 		arcmsr_free_resource(acb);
2074ad6d6297SScott Long 		printf("arcmsr%d: map free srb failure!\n", acb->pci_unit);
2075f1c579b1SScott Long 		return ENXIO;
2076f1c579b1SScott Long 	}
2077ad6d6297SScott Long 	acb->btag=rman_get_bustag(acb->sys_res_arcmsr);
2078ad6d6297SScott Long 	acb->bhandle=rman_get_bushandle(acb->sys_res_arcmsr);
2079ad6d6297SScott Long 	acb->pmu=(struct MessageUnit *)mem_base;
2080ad6d6297SScott Long 	acb->acb_flags  |= (ACB_F_MESSAGE_WQBUFFER_CLEARED
2081ad6d6297SScott Long 			|ACB_F_MESSAGE_RQBUFFER_CLEARED
2082ad6d6297SScott Long 			|ACB_F_MESSAGE_WQBUFFER_READED);
2083ad6d6297SScott Long 	acb->acb_flags &= ~ACB_F_SCSISTOPADAPTER;
2084ad6d6297SScott Long 	/*
2085ad6d6297SScott Long 	********************************************************************
2086ad6d6297SScott Long 	** init raid volume state
2087ad6d6297SScott Long 	********************************************************************
2088ad6d6297SScott Long 	*/
2089ad6d6297SScott Long 	for(i=0;i<ARCMSR_MAX_TARGETID;i++) {
2090ad6d6297SScott Long 		for(j=0;j<ARCMSR_MAX_TARGETLUN;j++) {
2091ad6d6297SScott Long 			acb->devstate[i][j]=ARECA_RAID_GOOD;
2092ad6d6297SScott Long 		}
2093ad6d6297SScott Long 	}
2094ad6d6297SScott Long 	/* disable iop all outbound interrupt */
2095ad6d6297SScott Long 	intmask_org=CHIP_REG_READ32(outbound_intmask);
2096ad6d6297SScott Long 	CHIP_REG_WRITE32(outbound_intmask, intmask_org|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE);
2097ad6d6297SScott Long 	arcmsr_iop_init(acb);
2098f1c579b1SScott Long 	return(0);
2099f1c579b1SScott Long }
2100f1c579b1SScott Long /*
2101f1c579b1SScott Long ************************************************************************
2102f1c579b1SScott Long ************************************************************************
2103f1c579b1SScott Long */
2104ad6d6297SScott Long static u_int32_t arcmsr_attach(device_t dev)
2105f1c579b1SScott Long {
2106ad6d6297SScott Long 	struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev);
2107ad6d6297SScott Long 	u_int32_t unit=device_get_unit(dev);
2108f1c579b1SScott Long 	struct ccb_setasync csa;
2109f1c579b1SScott Long 	struct cam_devq	*devq;	/* Device Queue to use for this SIM */
2110f1c579b1SScott Long 	struct resource	*irqres;
2111f1c579b1SScott Long 	int	rid;
2112f1c579b1SScott Long 
2113ad6d6297SScott Long 	if(acb == NULL) {
2114ad6d6297SScott Long 		printf("arcmsr%d: cannot allocate softc\n", unit);
2115ad6d6297SScott Long 		return (ENOMEM);
2116ad6d6297SScott Long 	}
2117ad6d6297SScott Long 	bzero(acb, sizeof(struct AdapterControlBlock));
2118ad6d6297SScott Long 	if(arcmsr_initialize(dev)) {
2119ad6d6297SScott Long 		printf("arcmsr%d: initialize failure!\n", unit);
2120f1c579b1SScott Long 		return ENXIO;
2121f1c579b1SScott Long 	}
2122f1c579b1SScott Long 	/* After setting up the adapter, map our interrupt */
2123f1c579b1SScott Long 	rid=0;
2124ad6d6297SScott Long 	irqres=bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0ul, ~0ul, 1, RF_SHAREABLE | RF_ACTIVE);
2125ad6d6297SScott Long 	if(irqres == NULL ||
2126ad6d6297SScott Long 	bus_setup_intr(dev, irqres, INTR_TYPE_CAM|INTR_ENTROPY|INTR_MPSAFE
2127ef544f63SPaolo Pisati   		, NULL, arcmsr_interrupt, acb, &acb->ih))  {
2128ad6d6297SScott Long 		arcmsr_free_resource(acb);
2129f1c579b1SScott Long 		printf("arcmsr%d: unable to register interrupt handler!\n", unit);
2130f1c579b1SScott Long 		return ENXIO;
2131f1c579b1SScott Long 	}
2132ad6d6297SScott Long 	acb->irqres=irqres;
2133ad6d6297SScott Long 	acb->pci_dev=dev;
2134ad6d6297SScott Long 	acb->pci_unit=unit;
2135f1c579b1SScott Long 	/*
2136f1c579b1SScott Long 	 * Now let the CAM generic SCSI layer find the SCSI devices on
2137f1c579b1SScott Long 	 * the bus *  start queue to reset to the idle loop. *
2138f1c579b1SScott Long 	 * Create device queue of SIM(s) *  (MAX_START_JOB - 1) :
2139f1c579b1SScott Long 	 * max_sim_transactions
2140f1c579b1SScott Long 	*/
2141f1c579b1SScott Long 	devq=cam_simq_alloc(ARCMSR_MAX_START_JOB);
2142ad6d6297SScott Long 	if(devq == NULL) {
2143ad6d6297SScott Long 	    arcmsr_free_resource(acb);
2144ad6d6297SScott Long 		bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres);
2145ad6d6297SScott Long 		printf("arcmsr%d: cam_simq_alloc failure!\n", unit);
2146f1c579b1SScott Long 		return ENXIO;
2147f1c579b1SScott Long 	}
21482b83592fSScott Long 	acb->psim=cam_sim_alloc(arcmsr_action, arcmsr_poll,
21492b83592fSScott Long 		"arcmsr", acb, unit, &Giant, 1,
21502b83592fSScott Long 		ARCMSR_MAX_OUTSTANDING_CMD, devq);
2151ad6d6297SScott Long 	if(acb->psim == NULL) {
2152ad6d6297SScott Long 		arcmsr_free_resource(acb);
2153ad6d6297SScott Long 		bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres);
2154f1c579b1SScott Long 		cam_simq_free(devq);
2155ad6d6297SScott Long 		printf("arcmsr%d: cam_sim_alloc failure!\n", unit);
2156f1c579b1SScott Long 		return ENXIO;
2157f1c579b1SScott Long 	}
2158b50569b7SScott Long 	if(xpt_bus_register(acb->psim, dev, 0) != CAM_SUCCESS) {
2159ad6d6297SScott Long 		arcmsr_free_resource(acb);
2160ad6d6297SScott Long 		bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres);
2161ad6d6297SScott Long 		cam_sim_free(acb->psim, /*free_devq*/TRUE);
2162ad6d6297SScott Long 		printf("arcmsr%d: xpt_bus_register failure!\n", unit);
2163f1c579b1SScott Long 		return ENXIO;
2164f1c579b1SScott Long 	}
2165ad6d6297SScott Long  	if(xpt_create_path(&acb->ppath, /* periph */ NULL
2166ad6d6297SScott Long 		, cam_sim_path(acb->psim)
2167ad6d6297SScott Long 		, CAM_TARGET_WILDCARD
2168ad6d6297SScott Long 		, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
2169ad6d6297SScott Long 		arcmsr_free_resource(acb);
2170ad6d6297SScott Long 		bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres);
2171ad6d6297SScott Long 		xpt_bus_deregister(cam_sim_path(acb->psim));
2172ad6d6297SScott Long 		cam_sim_free(acb->psim, /* free_simq */ TRUE);
2173ad6d6297SScott Long 		printf("arcmsr%d: xpt_create_path failure!\n", unit);
2174f1c579b1SScott Long 		return ENXIO;
2175f1c579b1SScott Long 	}
2176ad6d6297SScott Long 	ARCMSR_LOCK_INIT(&acb->workingQ_done_lock, "arcmsr done working Q lock");
2177ad6d6297SScott Long 	ARCMSR_LOCK_INIT(&acb->workingQ_start_lock, "arcmsr start working Q lock");
2178ad6d6297SScott Long 	ARCMSR_LOCK_INIT(&acb->qbuffer_lock, "arcmsr Q buffer lock");
2179f1c579b1SScott Long 	/*
2180f1c579b1SScott Long 	****************************************************
2181f1c579b1SScott Long 	*/
2182ad6d6297SScott Long 	xpt_setup_ccb(&csa.ccb_h, acb->ppath, /*priority*/5);
2183f1c579b1SScott Long 	csa.ccb_h.func_code=XPT_SASYNC_CB;
2184f1c579b1SScott Long 	csa.event_enable=AC_FOUND_DEVICE|AC_LOST_DEVICE;
2185f1c579b1SScott Long 	csa.callback=arcmsr_async;
2186ad6d6297SScott Long 	csa.callback_arg=acb->psim;
2187f1c579b1SScott Long 	xpt_action((union ccb *)&csa);
2188f1c579b1SScott Long 	/* Create the control device.  */
2189ad6d6297SScott Long 	acb->ioctl_dev=make_dev(&arcmsr_cdevsw
2190ad6d6297SScott Long 		, unit
2191ad6d6297SScott Long 		, UID_ROOT
2192ad6d6297SScott Long 		, GID_WHEEL /* GID_OPERATOR */
2193ad6d6297SScott Long 		, S_IRUSR | S_IWUSR
2194ad6d6297SScott Long 		, "arcmsr%d", unit);
2195f1c579b1SScott Long #if __FreeBSD_version < 503000
2196ad6d6297SScott Long 	acb->ioctl_dev->si_drv1=acb;
2197f1c579b1SScott Long #endif
2198f1c579b1SScott Long #if __FreeBSD_version > 500005
2199ad6d6297SScott Long 	(void)make_dev_alias(acb->ioctl_dev, "arc%d", unit);
2200f1c579b1SScott Long #endif
2201f1c579b1SScott Long 	return 0;
2202f1c579b1SScott Long }
2203f1c579b1SScott Long /*
2204f1c579b1SScott Long ************************************************************************
2205f1c579b1SScott Long ************************************************************************
2206f1c579b1SScott Long */
2207ad6d6297SScott Long static u_int32_t arcmsr_probe(device_t dev)
2208f1c579b1SScott Long {
2209ad6d6297SScott Long 	u_int32_t id;
2210ad6d6297SScott Long 	static char buf[256];
2211ad6d6297SScott Long 	char *type;
2212ad6d6297SScott Long 	int raid6 = 1;
2213ad6d6297SScott Long 
2214ad6d6297SScott Long 	if (pci_get_vendor(dev) != PCI_VENDOR_ID_ARECA) {
2215ad6d6297SScott Long 		return (ENXIO);
2216ad6d6297SScott Long 	}
2217ad6d6297SScott Long 	switch(id=pci_get_devid(dev)) {
2218f1c579b1SScott Long 	case PCIDevVenIDARC1110:
2219f1c579b1SScott Long 	case PCIDevVenIDARC1210:
2220ad6d6297SScott Long 		raid6 = 0;
2221ad6d6297SScott Long 		/*FALLTHRU*/
2222ad6d6297SScott Long 	case PCIDevVenIDARC1120:
2223ad6d6297SScott Long 	case PCIDevVenIDARC1130:
2224ad6d6297SScott Long 	case PCIDevVenIDARC1160:
2225ad6d6297SScott Long 	case PCIDevVenIDARC1170:
2226f1c579b1SScott Long 	case PCIDevVenIDARC1220:
2227f1c579b1SScott Long 	case PCIDevVenIDARC1230:
2228f1c579b1SScott Long 	case PCIDevVenIDARC1260:
2229ad6d6297SScott Long 	case PCIDevVenIDARC1270:
2230ad6d6297SScott Long 	case PCIDevVenIDARC1280:
2231ad6d6297SScott Long 		type = "SATA";
2232ad6d6297SScott Long 		break;
2233ad6d6297SScott Long 	case PCIDevVenIDARC1380:
2234ad6d6297SScott Long 	case PCIDevVenIDARC1381:
2235ad6d6297SScott Long 	case PCIDevVenIDARC1680:
2236ad6d6297SScott Long 	case PCIDevVenIDARC1681:
2237ad6d6297SScott Long 		type = "SAS";
2238ad6d6297SScott Long 		break;
2239ad6d6297SScott Long 	default:
2240ad6d6297SScott Long 		type = "X-TYPE";
2241ad6d6297SScott Long 		break;
2242f1c579b1SScott Long 	}
2243ad6d6297SScott Long 	sprintf(buf, "Areca %s Host Adapter RAID Controller %s\n", type, raid6 ? "(RAID6 capable)" : "");
2244ad6d6297SScott Long 	device_set_desc_copy(dev, buf);
2245ad6d6297SScott Long 	return 0;
2246f1c579b1SScott Long }
2247f1c579b1SScott Long /*
2248f1c579b1SScott Long ************************************************************************
2249f1c579b1SScott Long ************************************************************************
2250f1c579b1SScott Long */
2251ad6d6297SScott Long static void arcmsr_shutdown(device_t dev)
2252f1c579b1SScott Long {
2253ad6d6297SScott Long 	u_int32_t  i, poll_count=0;
2254ad6d6297SScott Long 	u_int32_t intmask_org;
2255ad6d6297SScott Long 	struct CommandControlBlock *srb;
2256ad6d6297SScott Long 	struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev);
2257f1c579b1SScott Long 
2258f1c579b1SScott Long 	/* stop adapter background rebuild */
2259ad6d6297SScott Long 	arcmsr_stop_adapter_bgrb(acb);
2260ad6d6297SScott Long 	arcmsr_flush_adapter_cache(acb);
2261ad6d6297SScott Long 	/* disable all outbound interrupt */
2262ad6d6297SScott Long 	intmask_org=CHIP_REG_READ32(outbound_intmask);
2263ad6d6297SScott Long 	CHIP_REG_WRITE32(outbound_intmask, (intmask_org|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE));
2264f1c579b1SScott Long 	/* abort all outstanding command */
2265ad6d6297SScott Long 	acb->acb_flags |= ACB_F_SCSISTOPADAPTER;
2266ad6d6297SScott Long 	acb->acb_flags &= ~ACB_F_IOP_INITED;
2267ad6d6297SScott Long 	if(acb->srboutstandingcount!=0) {
2268ad6d6297SScott Long 		while((acb->srboutstandingcount!=0) && (poll_count < 256)) {
2269ad6d6297SScott Long 			arcmsr_interrupt((void *)acb);
2270ad6d6297SScott Long 			UDELAY(25000);
2271ad6d6297SScott Long 			poll_count++;
2272f1c579b1SScott Long 		}
2273ad6d6297SScott Long 		if(acb->srboutstandingcount!=0) {
2274ad6d6297SScott Long 			arcmsr_abort_allcmd(acb);
2275ad6d6297SScott Long 			/*clear all outbound posted Q*/
2276ad6d6297SScott Long 			for(i=0;i<ARCMSR_MAX_OUTSTANDING_CMD;i++) {
2277ad6d6297SScott Long 				CHIP_REG_READ32(outbound_queueport);
2278f1c579b1SScott Long 			}
2279ad6d6297SScott Long 			for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++) {
2280ad6d6297SScott Long 				srb=acb->psrb_pool[i];
2281ad6d6297SScott Long 				if(srb->startdone==ARCMSR_SRB_START) {
2282ad6d6297SScott Long 					srb->startdone=ARCMSR_SRB_ABORTED;
2283ad6d6297SScott Long 					srb->pccb->ccb_h.status |= CAM_REQ_ABORTED;
2284ad6d6297SScott Long 					arcmsr_srb_complete(srb, 1);
2285f1c579b1SScott Long 				}
2286f1c579b1SScott Long 			}
2287f1c579b1SScott Long 		}
2288ad6d6297SScott Long 	}
2289ad6d6297SScott Long 	atomic_set_int(&acb->srboutstandingcount, 0);
2290ad6d6297SScott Long 	acb->workingsrb_doneindex=0;
2291ad6d6297SScott Long 	acb->workingsrb_startindex=0;
2292f1c579b1SScott Long 	return;
2293f1c579b1SScott Long }
2294f1c579b1SScott Long /*
2295f1c579b1SScott Long ************************************************************************
2296f1c579b1SScott Long ************************************************************************
2297f1c579b1SScott Long */
2298ad6d6297SScott Long static u_int32_t arcmsr_detach(device_t dev)
2299f1c579b1SScott Long {
2300ad6d6297SScott Long 	struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev);
2301f1c579b1SScott Long 
2302f1c579b1SScott Long 	arcmsr_shutdown(dev);
2303ad6d6297SScott Long 	arcmsr_free_resource(acb);
2304ad6d6297SScott Long 	bus_release_resource(dev, SYS_RES_MEMORY, PCIR_BAR(0), acb->sys_res_arcmsr);
2305ad6d6297SScott Long 	bus_teardown_intr(dev, acb->irqres, acb->ih);
2306ad6d6297SScott Long 	bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres);
2307ad6d6297SScott Long 	xpt_async(AC_LOST_DEVICE, acb->ppath, NULL);
2308ad6d6297SScott Long 	xpt_free_path(acb->ppath);
2309ad6d6297SScott Long 	xpt_bus_deregister(cam_sim_path(acb->psim));
2310ad6d6297SScott Long 	cam_sim_free(acb->psim, TRUE);
2311f1c579b1SScott Long 	return (0);
2312f1c579b1SScott Long }
2313f1c579b1SScott Long 
2314f1c579b1SScott Long 
2315