xref: /freebsd/sys/dev/arcmsr/arcmsr.c (revision f1c579b1ec70d6265f48b1b7059ac627ad2e0396)
1f1c579b1SScott Long /*
2f1c579b1SScott Long ******************************************************************************************
3f1c579b1SScott Long **        O.S   : FreeBSD
4f1c579b1SScott Long **   FILE NAME  : arcmsr.c
5f1c579b1SScott Long **        BY    : Erich Chen
6f1c579b1SScott Long **   Description: SCSI RAID Device Driver for
7f1c579b1SScott Long **                ARECA (ARC1110/1120/1160/1210/1220/1260) SATA RAID HOST Adapter
8f1c579b1SScott Long **                ARCMSR RAID Host adapter[RAID controller:INTEL 331(PCI-X) 341(PCI-EXPRESS) chip set]
9f1c579b1SScott Long ******************************************************************************************
10f1c579b1SScott Long ************************************************************************
11f1c579b1SScott Long **
12f1c579b1SScott Long ** Copyright (c) 2004-2006 ARECA Co. Ltd.
13f1c579b1SScott Long **        Erich Chen, Taipei Taiwan All rights reserved.
14f1c579b1SScott Long **
15f1c579b1SScott Long ** Redistribution and use in source and binary forms,with or without
16f1c579b1SScott Long ** modification,are permitted provided that the following conditions
17f1c579b1SScott Long ** are met:
18f1c579b1SScott Long ** 1. Redistributions of source code must retain the above copyright
19f1c579b1SScott Long **    notice,this list of conditions and the following disclaimer.
20f1c579b1SScott Long ** 2. Redistributions in binary form must reproduce the above copyright
21f1c579b1SScott Long **    notice,this list of conditions and the following disclaimer in the
22f1c579b1SScott Long **    documentation and/or other materials provided with the distribution.
23f1c579b1SScott Long ** 3. The name of the author may not be used to endorse or promote products
24f1c579b1SScott Long **    derived from this software without specific prior written permission.
25f1c579b1SScott Long **
26f1c579b1SScott Long ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
27f1c579b1SScott Long ** IMPLIED WARRANTIES,INCLUDING,BUT NOT LIMITED TO,THE IMPLIED WARRANTIES
28f1c579b1SScott Long ** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
29f1c579b1SScott Long ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,INDIRECT,
30f1c579b1SScott Long ** INCIDENTAL,SPECIAL,EXEMPLARY,OR CONSEQUENTIAL DAMAGES(INCLUDING,BUT
31f1c579b1SScott Long ** NOT LIMITED TO,PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32f1c579b1SScott Long ** DATA,OR PROFITS; OR BUSINESS INTERRUPTION)HOWEVER CAUSED AND ON ANY
33f1c579b1SScott Long ** THEORY OF LIABILITY,WHETHER IN CONTRACT,STRICT LIABILITY,OR TORT
34f1c579b1SScott Long **(INCLUDING NEGLIGENCE OR OTHERWISE)ARISING IN ANY WAY OUT OF THE USE OF
35f1c579b1SScott Long ** THIS SOFTWARE,EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36f1c579b1SScott Long **************************************************************************
37f1c579b1SScott Long ** History
38f1c579b1SScott Long **
39f1c579b1SScott Long **        REV#         DATE	            NAME	         DESCRIPTION
40f1c579b1SScott Long **     1.00.00.00    3/31/2004	       Erich Chen	     First release
41f1c579b1SScott Long **     1.20.00.02   11/29/2004         Erich Chen        bug fix with arcmsr_bus_reset when PHY error
42f1c579b1SScott Long ******************************************************************************************
43f1c579b1SScott Long ** $FreeBSD$
44f1c579b1SScott Long */
45f1c579b1SScott Long #define ARCMSR_DEBUG            1
46f1c579b1SScott Long /*
47f1c579b1SScott Long **********************************
48f1c579b1SScott Long */
49f1c579b1SScott Long #include <sys/param.h>
50f1c579b1SScott Long #include <sys/systm.h>
51f1c579b1SScott Long #include <sys/malloc.h>
52f1c579b1SScott Long #include <sys/kernel.h>
53f1c579b1SScott Long #include <sys/bus.h>
54f1c579b1SScott Long #include <sys/queue.h>
55f1c579b1SScott Long #include <sys/stat.h>
56f1c579b1SScott Long #include <sys/devicestat.h>
57f1c579b1SScott Long #include <sys/kthread.h>
58f1c579b1SScott Long #include <sys/module.h>
59f1c579b1SScott Long #include <sys/proc.h>
60f1c579b1SScott Long #include <sys/lock.h>
61f1c579b1SScott Long #include <sys/sysctl.h>
62f1c579b1SScott Long #include <sys/poll.h>
63f1c579b1SScott Long #include <sys/ioccom.h>
64f1c579b1SScott Long #include <vm/vm.h>
65f1c579b1SScott Long #include <vm/vm_param.h>
66f1c579b1SScott Long #include <vm/pmap.h>
67f1c579b1SScott Long 
68f1c579b1SScott Long #include <isa/rtc.h>
69f1c579b1SScott Long 
70f1c579b1SScott Long #include <machine/bus_memio.h>
71f1c579b1SScott Long #include <machine/bus.h>
72f1c579b1SScott Long #include <machine/clock.h>
73f1c579b1SScott Long #include <machine/resource.h>
74f1c579b1SScott Long #include <machine/atomic.h>
75f1c579b1SScott Long #include <sys/conf.h>
76f1c579b1SScott Long #include <sys/rman.h>
77f1c579b1SScott Long 
78f1c579b1SScott Long #include <cam/cam.h>
79f1c579b1SScott Long #include <cam/cam_ccb.h>
80f1c579b1SScott Long #include <cam/cam_sim.h>
81f1c579b1SScott Long #include <cam/cam_xpt_sim.h>
82f1c579b1SScott Long #include <cam/cam_debug.h>
83f1c579b1SScott Long #include <cam/scsi/scsi_all.h>
84f1c579b1SScott Long #include <cam/scsi/scsi_message.h>
85f1c579b1SScott Long /*
86f1c579b1SScott Long **************************************************************************
87f1c579b1SScott Long ** Define the OS version specific locks
88f1c579b1SScott Long **************************************************************************
89f1c579b1SScott Long */
90f1c579b1SScott Long #if __FreeBSD_version >= 500005
91f1c579b1SScott Long     #include <sys/selinfo.h>
92f1c579b1SScott Long 	#include <sys/mutex.h>
93f1c579b1SScott Long     #include <dev/pci/pcivar.h>
94f1c579b1SScott Long     #include <dev/pci/pcireg.h>
95f1c579b1SScott Long 	#define ARCMSR_LOCK_INIT(l, s)	        mtx_init(l, s,NULL, MTX_DEF|MTX_RECURSE)
96f1c579b1SScott Long 	#define ARCMSR_LOCK_ACQUIRE(l)	        mtx_lock(l)
97f1c579b1SScott Long 	#define ARCMSR_LOCK_RELEASE(l)	        mtx_unlock(l)
98f1c579b1SScott Long 	typedef struct mtx                      arcmsr_lock_t;
99f1c579b1SScott Long #else
100f1c579b1SScott Long     #include <sys/select.h>
101f1c579b1SScott Long     #include <pci/pcivar.h>
102f1c579b1SScott Long     #include <pci/pcireg.h>
103f1c579b1SScott Long 	#define ARCMSR_LOCK_INIT(l, s)	        simple_lock_init(l)
104f1c579b1SScott Long 	#define ARCMSR_LOCK_ACQUIRE(l)	        simple_lock(l)
105f1c579b1SScott Long 	#define ARCMSR_LOCK_RELEASE(l)	        simple_unlock(l)
106f1c579b1SScott Long 	typedef struct simplelock               arcmsr_lock_t;
107f1c579b1SScott Long #endif
108f1c579b1SScott Long #include <dev/arcmsr/arcmsr.h>
109f1c579b1SScott Long /*
110f1c579b1SScott Long **************************************************************************
111f1c579b1SScott Long ** __FreeBSD_version 502010
112f1c579b1SScott Long **************************************************************************
113f1c579b1SScott Long */
114f1c579b1SScott Long static VOID arcmsr_interrupt(VOID *arg);
115f1c579b1SScott Long static LONG arcmsr_probe(device_t dev);
116f1c579b1SScott Long static LONG arcmsr_attach(device_t dev);
117f1c579b1SScott Long static LONG arcmsr_detach(device_t dev);
118f1c579b1SScott Long static VOID arcmsr_shutdown(device_t dev);
119f1c579b1SScott Long ULONG arcmsr_make_timespec(ULONG year,ULONG mon,ULONG day,ULONG hour,ULONG min,ULONG sec);
120f1c579b1SScott Long ULONG arcmsr_getcmos_time(VOID);
121f1c579b1SScott Long LONG arcmsr_queue_dpc(PACB pACB,DPCFUN dpcfun,VOID *arg);
122f1c579b1SScott Long LONG arcmsr_iop_ioctlcmd(PACB pACB,ULONG ioctl_cmd,caddr_t arg);
123f1c579b1SScott Long BOOLEAN arcmsr_seek_cmd2abort(union ccb * pabortccb);
124f1c579b1SScott Long BOOLEAN arcmsr_wait_msgint_ready(PACB pACB);
125f1c579b1SScott Long PSRB arcmsr_get_freesrb(PACB pACB);
126f1c579b1SScott Long VOID arcmsr_free_resource(PACB pACB);
127f1c579b1SScott Long VOID arcmsr_bus_reset(PACB pACB);
128f1c579b1SScott Long VOID arcmsr_stop_adapter_bgrb(PACB pACB);
129f1c579b1SScott Long VOID arcmsr_start_adapter_bgrb(PACB pACB);
130f1c579b1SScott Long VOID arcmsr_iop_init(PACB pACB);
131f1c579b1SScott Long VOID arcmsr_do_dpcQ(PACB pACB);
132f1c579b1SScott Long VOID arcmsr_flush_adapter_cache(PACB pACB);
133f1c579b1SScott Long VOID arcmsr_do_thread_works(VOID *arg);
134f1c579b1SScott Long VOID arcmsr_queue_wait2go_srb(PACB pACB,PSRB pSRB);
135f1c579b1SScott Long VOID arcmsr_post_wait2go_srb(PACB pACB);
136f1c579b1SScott Long VOID arcmsr_post_Qbuffer(PACB pACB);
137f1c579b1SScott Long VOID arcmsr_abort_allcmd(PACB pACB);
138f1c579b1SScott Long VOID arcmsr_srb_complete(PSRB pSRB);
139f1c579b1SScott Long VOID arcmsr_iop_reset(PACB pACB);
140f1c579b1SScott Long VOID arcmsr_report_SenseInfoBuffer(PSRB pSRB);
141f1c579b1SScott Long VOID arcmsr_build_srb(PSRB pSRB, bus_dma_segment_t *dm_segs, LONG nseg);
142f1c579b1SScott Long /*
143f1c579b1SScott Long *****************************************************************************************
144f1c579b1SScott Long ** Character device switch table
145f1c579b1SScott Long **struct cdevsw {
146f1c579b1SScott Long **	d_open_t		*d_open;
147f1c579b1SScott Long **	d_close_t		*d_close;
148f1c579b1SScott Long **	d_read_t		*d_read;
149f1c579b1SScott Long **	d_write_t		*d_write;
150f1c579b1SScott Long **	d_ioctl_t		*d_ioctl;
151f1c579b1SScott Long **	d_poll_t		*d_poll;
152f1c579b1SScott Long **	d_mmap_t		*d_mmap;
153f1c579b1SScott Long **	d_strategy_t	*d_strategy;
154f1c579b1SScott Long **	const char	    *d_name;	   "" base device name, e.g. 'vn'
155f1c579b1SScott Long **	int		         d_maj;
156f1c579b1SScott Long **	d_dump_t	    *d_dump;
157f1c579b1SScott Long **	d_psize_t	    *d_psize;
158f1c579b1SScott Long **	u_int		     d_flags;
159f1c579b1SScott Long **	int		         d_bmaj;
160f1c579b1SScott Long **	d_kqfilter_t	*d_kqfilter;   "" additions below are not binary compatible with 4.2 and below
161f1c579b1SScott Long **};
162f1c579b1SScott Long ******************************************************************************************
163f1c579b1SScott Long */
164f1c579b1SScott Long /*
165f1c579b1SScott Long **************************************************************************
166f1c579b1SScott Long ** Insert a delay in micro-seconds and milli-seconds.
167f1c579b1SScott Long ** static void MDELAY(LONG ms) { while (ms--) UDELAY(1000); }
168f1c579b1SScott Long **************************************************************************
169f1c579b1SScott Long */
170f1c579b1SScott Long static VOID UDELAY(LONG us) { DELAY(us); }
171f1c579b1SScott Long /*
172f1c579b1SScott Long **************************************************************************
173f1c579b1SScott Long **
174f1c579b1SScott Long **************************************************************************
175f1c579b1SScott Long */
176f1c579b1SScott Long static bus_dmamap_callback_t arcmsr_map_freesrb;
177f1c579b1SScott Long static bus_dmamap_callback_t arcmsr_executesrb;
178f1c579b1SScott Long /*
179f1c579b1SScott Long **************************************************************************
180f1c579b1SScott Long **
181f1c579b1SScott Long **************************************************************************
182f1c579b1SScott Long */
183f1c579b1SScott Long static d_open_t	arcmsr_open;
184f1c579b1SScott Long static d_close_t arcmsr_close;
185f1c579b1SScott Long static d_ioctl_t arcmsr_ioctl;
186f1c579b1SScott Long 
187f1c579b1SScott Long static device_method_t arcmsr_methods[]={
188f1c579b1SScott Long 	DEVMETHOD(device_probe,		arcmsr_probe),
189f1c579b1SScott Long 	DEVMETHOD(device_attach,	arcmsr_attach),
190f1c579b1SScott Long 	DEVMETHOD(device_detach,	arcmsr_detach),
191f1c579b1SScott Long     DEVMETHOD(device_shutdown,	arcmsr_shutdown),
192f1c579b1SScott Long 	{ 0,0 }
193f1c579b1SScott Long };
194f1c579b1SScott Long 
195f1c579b1SScott Long static driver_t arcmsr_driver={
196f1c579b1SScott Long 	"arcmsr",arcmsr_methods,sizeof(struct _ACB)
197f1c579b1SScott Long };
198f1c579b1SScott Long 
199f1c579b1SScott Long static devclass_t arcmsr_devclass;
200f1c579b1SScott Long DRIVER_MODULE(arcmsr,pci,arcmsr_driver,arcmsr_devclass,0,0);
201f1c579b1SScott Long 
202f1c579b1SScott Long #if __FreeBSD_version >= 502010
203f1c579b1SScott Long 	static struct cdevsw arcmsr_cdevsw={
204f1c579b1SScott Long 	    .d_version = D_VERSION,
205f1c579b1SScott Long 	    .d_flags   = D_NEEDGIANT,
206f1c579b1SScott Long 		.d_open    = arcmsr_open,		/* open     */
207f1c579b1SScott Long 		.d_close   = arcmsr_close,		/* close    */
208f1c579b1SScott Long 		.d_ioctl   = arcmsr_ioctl,		/* ioctl    */
209f1c579b1SScott Long 		.d_name    = "arcmsr",			/* name     */
210f1c579b1SScott Long 	};
211f1c579b1SScott Long #else
212f1c579b1SScott Long 	#define ARCMSR_CDEV_MAJOR	180
213f1c579b1SScott Long 
214f1c579b1SScott Long 	static struct cdevsw arcmsr_cdevsw = {
215f1c579b1SScott Long 		arcmsr_open,		        /* open     */
216f1c579b1SScott Long 		arcmsr_close,		        /* close    */
217f1c579b1SScott Long 		noread,			            /* read     */
218f1c579b1SScott Long 		nowrite,		            /* write    */
219f1c579b1SScott Long 		arcmsr_ioctl,		        /* ioctl    */
220f1c579b1SScott Long 		nopoll,		                /* poll     */
221f1c579b1SScott Long 		nommap,			            /* mmap     */
222f1c579b1SScott Long 		nostrategy,		            /* strategy */
223f1c579b1SScott Long 		"arcmsr",			        /* name     */
224f1c579b1SScott Long 		ARCMSR_CDEV_MAJOR,		    /* major    */
225f1c579b1SScott Long 		nodump,			            /* dump     */
226f1c579b1SScott Long 		nopsize,		            /* psize    */
227f1c579b1SScott Long 		0			                /* flags    */
228f1c579b1SScott Long 	};
229f1c579b1SScott Long #endif
230f1c579b1SScott Long 
231f1c579b1SScott Long #if __FreeBSD_version < 500005
232f1c579b1SScott Long     static int arcmsr_open(dev_t dev, int flags, int fmt, struct proc *proc)
233f1c579b1SScott Long #else
234f1c579b1SScott Long     #if __FreeBSD_version < 503000
235f1c579b1SScott Long         static int arcmsr_open(dev_t dev, int flags, int fmt, struct thread *proc)
236f1c579b1SScott Long     #else
237f1c579b1SScott Long         static int arcmsr_open(struct cdev *dev, int flags, int fmt, d_thread_t *proc)
238f1c579b1SScott Long     #endif
239f1c579b1SScott Long #endif
240f1c579b1SScott Long {
241f1c579b1SScott Long 	#if __FreeBSD_version < 503000
242f1c579b1SScott Long 	    PACB pACB=dev->si_drv1;
243f1c579b1SScott Long     #else
244f1c579b1SScott Long 		int	unit = minor(dev);
245f1c579b1SScott Long 		PACB pACB = devclass_get_softc(arcmsr_devclass, unit);
246f1c579b1SScott Long     #endif
247f1c579b1SScott Long 
248f1c579b1SScott Long 	if(pACB==NULL)
249f1c579b1SScott Long 	{
250f1c579b1SScott Long 		return ENXIO;
251f1c579b1SScott Long 	}
252f1c579b1SScott Long 	/* Check to make sure the device isn't already open */
253f1c579b1SScott Long 	if (pACB->acb_flags & ACB_F_IOCTL_OPEN)
254f1c579b1SScott Long 	{
255f1c579b1SScott Long 		return EBUSY;
256f1c579b1SScott Long 	}
257f1c579b1SScott Long 	pACB->acb_flags |= ACB_F_IOCTL_OPEN;
258f1c579b1SScott Long 	return 0;
259f1c579b1SScott Long }
260f1c579b1SScott Long /*
261f1c579b1SScott Long **************************************************************************
262f1c579b1SScott Long **************************************************************************
263f1c579b1SScott Long */
264f1c579b1SScott Long #if __FreeBSD_version < 500005
265f1c579b1SScott Long     static int arcmsr_close(dev_t dev, int flags, int fmt, struct proc *proc)
266f1c579b1SScott Long #else
267f1c579b1SScott Long     #if __FreeBSD_version < 503000
268f1c579b1SScott Long         static int arcmsr_close(dev_t dev, int flags, int fmt, struct thread *proc)
269f1c579b1SScott Long     #else
270f1c579b1SScott Long         static int arcmsr_close(struct cdev *dev, int flags, int fmt, d_thread_t *proc)
271f1c579b1SScott Long     #endif
272f1c579b1SScott Long #endif
273f1c579b1SScott Long {
274f1c579b1SScott Long 	#if __FreeBSD_version < 503000
275f1c579b1SScott Long 	    PACB pACB=dev->si_drv1;
276f1c579b1SScott Long     #else
277f1c579b1SScott Long 		int	unit = minor(dev);
278f1c579b1SScott Long 		PACB pACB = devclass_get_softc(arcmsr_devclass, unit);
279f1c579b1SScott Long     #endif
280f1c579b1SScott Long 
281f1c579b1SScott Long 	if(pACB==NULL)
282f1c579b1SScott Long 	{
283f1c579b1SScott Long 		return ENXIO;
284f1c579b1SScott Long 	}
285f1c579b1SScott Long 	pACB->acb_flags &= ~ACB_F_IOCTL_OPEN;
286f1c579b1SScott Long 	return 0;
287f1c579b1SScott Long }
288f1c579b1SScott Long /*
289f1c579b1SScott Long **************************************************************************
290f1c579b1SScott Long **ENOENT
291f1c579b1SScott Long **ENOIOCTL
292f1c579b1SScott Long **ENOMEM
293f1c579b1SScott Long **EINVAL
294f1c579b1SScott Long **************************************************************************
295f1c579b1SScott Long */
296f1c579b1SScott Long #if __FreeBSD_version < 500005
297f1c579b1SScott Long     static int arcmsr_ioctl(dev_t dev, u_long ioctl_cmd, caddr_t arg, int flags, struct proc *proc)
298f1c579b1SScott Long #else
299f1c579b1SScott Long     #if __FreeBSD_version < 503000
300f1c579b1SScott Long         static int arcmsr_ioctl(dev_t dev, u_long ioctl_cmd, caddr_t arg, int flags, struct thread *proc)
301f1c579b1SScott Long     #else
302f1c579b1SScott Long         static int arcmsr_ioctl(struct cdev *dev, u_long ioctl_cmd, caddr_t arg,int flags, d_thread_t *proc)
303f1c579b1SScott Long     #endif
304f1c579b1SScott Long #endif
305f1c579b1SScott Long {
306f1c579b1SScott Long 	#if __FreeBSD_version < 503000
307f1c579b1SScott Long 	    PACB pACB=dev->si_drv1;
308f1c579b1SScott Long     #else
309f1c579b1SScott Long 		int	unit = minor(dev);
310f1c579b1SScott Long 		PACB pACB = devclass_get_softc(arcmsr_devclass, unit);
311f1c579b1SScott Long     #endif
312f1c579b1SScott Long 
313f1c579b1SScott Long 	if(pACB==NULL)
314f1c579b1SScott Long 	{
315f1c579b1SScott Long 		return ENXIO;
316f1c579b1SScott Long 	}
317f1c579b1SScott Long     return(arcmsr_iop_ioctlcmd(pACB,ioctl_cmd,arg));
318f1c579b1SScott Long }
319f1c579b1SScott Long /*
320f1c579b1SScott Long **************************************************************************
321f1c579b1SScott Long **************************************************************************
322f1c579b1SScott Long */
323f1c579b1SScott Long LONG arcmsr_queue_dpc(PACB pACB,DPCFUN dpcfun,VOID *arg)
324f1c579b1SScott Long {
325f1c579b1SScott Long 	ULONG s;
326f1c579b1SScott Long 	UCHAR index_pointer;
327f1c579b1SScott Long 
328f1c579b1SScott Long 	#if ARCMSR_DEBUG0
329f1c579b1SScott Long 	printf("arcmsr_queue_dpc................. \n");
330f1c579b1SScott Long 	#endif
331f1c579b1SScott Long 
332f1c579b1SScott Long     s=splcam();
333f1c579b1SScott Long 	index_pointer=(pACB->dpcQ_tail + 1) % ARCMSR_MAX_DPC;
334f1c579b1SScott Long 	if(index_pointer==pACB->dpcQ_head)
335f1c579b1SScott Long 	{
336f1c579b1SScott Long         splx(s);
337f1c579b1SScott Long 		printf("DPC Queue full!\n");
338f1c579b1SScott Long 		return -1;
339f1c579b1SScott Long 	}
340f1c579b1SScott Long 	pACB->dpcQ[pACB->dpcQ_tail].dpcfun=dpcfun;
341f1c579b1SScott Long 	pACB->dpcQ[pACB->dpcQ_tail].arg=arg;
342f1c579b1SScott Long 	pACB->dpcQ_tail=index_pointer;
343f1c579b1SScott Long 	/*
344f1c579b1SScott Long 	*********************************************************
345f1c579b1SScott Long 	*********************************************************
346f1c579b1SScott Long 	*/
347f1c579b1SScott Long 	wakeup(pACB->kthread_proc);
348f1c579b1SScott Long 
349f1c579b1SScott Long     splx(s);
350f1c579b1SScott Long 	return 0;
351f1c579b1SScott Long }
352f1c579b1SScott Long /*
353f1c579b1SScott Long **************************************************************************
354f1c579b1SScott Long **         arcmsr_do_dpcQ
355f1c579b1SScott Long **    execute dpc routine by kernel thread
356f1c579b1SScott Long ***************************************************************************
357f1c579b1SScott Long */
358f1c579b1SScott Long VOID arcmsr_do_dpcQ(PACB pACB)
359f1c579b1SScott Long {
360f1c579b1SScott Long 	#if ARCMSR_DEBUG0
361f1c579b1SScott Long 	printf("arcmsr_do_dpcQ................. \n");
362f1c579b1SScott Long 	#endif
363f1c579b1SScott Long 	/*
364f1c579b1SScott Long 	******************************************
365f1c579b1SScott Long 	******************************************
366f1c579b1SScott Long 	*/
367f1c579b1SScott Long 	while (pACB->dpcQ_head!=pACB->dpcQ_tail)
368f1c579b1SScott Long 	{
369f1c579b1SScott Long 		ULONG s;
370f1c579b1SScott Long 		DPC dpc;
371f1c579b1SScott Long 
372f1c579b1SScott Long 		/* got a "dpc routine" */
373f1c579b1SScott Long         s=splcam();
374f1c579b1SScott Long 		dpc=pACB->dpcQ[pACB->dpcQ_head];
375f1c579b1SScott Long 		pACB->dpcQ_head++;
376f1c579b1SScott Long 		pACB->dpcQ_head %=ARCMSR_MAX_DPC;
377f1c579b1SScott Long         splx(s);
378f1c579b1SScott Long 		/* execute this "dpc routine" */
379f1c579b1SScott Long 		dpc.dpcfun(dpc.arg);
380f1c579b1SScott Long 	}
381f1c579b1SScott Long 	return;
382f1c579b1SScott Long }
383f1c579b1SScott Long /*
384f1c579b1SScott Long **********************************************************************
385f1c579b1SScott Long ** <second> bit 05,04,03,02,01,00: 0 - 59
386f1c579b1SScott Long ** <minute> bit 11,10,09,08,07,06: 0 - 59
387f1c579b1SScott Long ** <month>  bit       15,14,13,12: 1 - 12
388f1c579b1SScott Long ** <hour>   bit 21,20,19,18,17,16: 0 - 59
389f1c579b1SScott Long ** <day>    bit    26,25,24,23,22: 1 - 31
390f1c579b1SScott Long ** <year>   bit    31,30,29,28,27: 0=2000,31=2031
391f1c579b1SScott Long **********************************************************************
392f1c579b1SScott Long */
393f1c579b1SScott Long ULONG arcmsr_make_timespec(ULONG year,ULONG mon,ULONG day,ULONG hour,ULONG min,ULONG sec)
394f1c579b1SScott Long {
395f1c579b1SScott Long     return((year<<27)|(day<<22)|(hour<<16)|(mon<<12)|(min<<6)|(sec));
396f1c579b1SScott Long }
397f1c579b1SScott Long /*
398f1c579b1SScott Long ********************************************************************
399f1c579b1SScott Long ********************************************************************
400f1c579b1SScott Long */
401f1c579b1SScott Long ULONG arcmsr_getcmos_time(VOID)
402f1c579b1SScott Long {
403f1c579b1SScott Long 	ULONG year,mon,day,hour,min,sec;
404f1c579b1SScott Long 
405f1c579b1SScott Long     #if ARCMSR_DEBUG0
406f1c579b1SScott Long     printf("arcmsr_getcmos_time \n");
407f1c579b1SScott Long     #endif
408f1c579b1SScott Long 	sec=bcd2bin(rtcin(RTC_SEC));
409f1c579b1SScott Long 	min=bcd2bin(rtcin(RTC_MIN));
410f1c579b1SScott Long 	hour=bcd2bin(rtcin(RTC_HRS));
411f1c579b1SScott Long 	day=bcd2bin(rtcin(RTC_DAY));
412f1c579b1SScott Long 	mon=bcd2bin(rtcin(RTC_MONTH));
413f1c579b1SScott Long 	year=bcd2bin(rtcin(RTC_YEAR));
414f1c579b1SScott Long 	if((year +=1900) < 1970)
415f1c579b1SScott Long 		year +=100;
416f1c579b1SScott Long 	return arcmsr_make_timespec(year,mon,day,hour,min,sec);
417f1c579b1SScott Long }
418f1c579b1SScott Long /*
419f1c579b1SScott Long *********************************************************************************
420f1c579b1SScott Long **  Asynchronous notification handler.
421f1c579b1SScott Long *********************************************************************************
422f1c579b1SScott Long */
423f1c579b1SScott Long static VOID arcmsr_async(VOID *cb_arg, ULONG code, struct cam_path *path, VOID *arg)
424f1c579b1SScott Long {
425f1c579b1SScott Long 	PACB pACB;
426f1c579b1SScott Long 	UCHAR target_id,target_lun;
427f1c579b1SScott Long 	struct cam_sim *sim;
428f1c579b1SScott Long 	ULONG s;
429f1c579b1SScott Long     #if ARCMSR_DEBUG0
430f1c579b1SScott Long     printf("arcmsr_async.......................................... \n");
431f1c579b1SScott Long     #endif
432f1c579b1SScott Long 	s=splcam();
433f1c579b1SScott Long 
434f1c579b1SScott Long 	sim=(struct cam_sim *) cb_arg;
435f1c579b1SScott Long 	pACB =(PACB) cam_sim_softc(sim);
436f1c579b1SScott Long 	switch (code)
437f1c579b1SScott Long 	{
438f1c579b1SScott Long 	case AC_LOST_DEVICE:
439f1c579b1SScott Long 		target_id=xpt_path_target_id(path);
440f1c579b1SScott Long         target_lun=xpt_path_lun_id(path);
441f1c579b1SScott Long 		if((target_id > ARCMSR_MAX_TARGETID) || (target_lun > ARCMSR_MAX_TARGETLUN))
442f1c579b1SScott Long 		{
443f1c579b1SScott Long 			break;
444f1c579b1SScott Long 		}
445f1c579b1SScott Long         printf("%s:scsi id%d lun%d device lost \n",device_get_name(pACB->pci_dev),target_id,target_lun);
446f1c579b1SScott Long 		break;
447f1c579b1SScott Long 	default:
448f1c579b1SScott Long 		break;
449f1c579b1SScott Long 	}
450f1c579b1SScott Long 	splx(s);
451f1c579b1SScott Long }
452f1c579b1SScott Long /*
453f1c579b1SScott Long **************************************************************************
454f1c579b1SScott Long *         arcmsr_do_thread_works
455f1c579b1SScott Long *    execute programs schedule by kernel thread
456f1c579b1SScott Long *    execute programs schedule by kernel thread
457f1c579b1SScott Long *      :do background rebuilding
458f1c579b1SScott Long *
459f1c579b1SScott Long * tsleep(void *ident,int priority,const char *wmesg,int timo)
460f1c579b1SScott Long * tsleep()
461f1c579b1SScott Long * General sleep call.  Suspends the current process until a wakeup is
462f1c579b1SScott Long * performed on the specified identifier.  The process will then be made
463f1c579b1SScott Long * runnable with the specified priority.  Sleeps at most timo/hz seconds
464f1c579b1SScott Long * (0 means no timeout).  If pri includes PCATCH flag, signals are checked
465f1c579b1SScott Long * before and after sleeping, else signals are not checked.  Returns 0 if
466f1c579b1SScott Long * awakened, EWOULDBLOCK if the timeout expires.  If PCATCH is set and a
467f1c579b1SScott Long * signal needs to be delivered, ERESTART is returned if the current system
468f1c579b1SScott Long * call should be restarted if possible, and EINTR is returned if the system
469f1c579b1SScott Long * call should be interrupted by the signal (return EINTR).
470f1c579b1SScott Long *
471f1c579b1SScott Long * await(int priority, int timo)
472f1c579b1SScott Long * await() - wait for async condition to occur.   The process blocks until
473f1c579b1SScott Long * wakeup() is called on the most recent asleep() address.  If wakeup is called
474f1c579b1SScott Long * priority to await(), await() winds up being a NOP.
475f1c579b1SScott Long *
476f1c579b1SScott Long * If await() is called more then once (without an intervening asleep() call),
477f1c579b1SScott Long * await() is still effectively a NOP but it calls mi_switch() to give other
478f1c579b1SScott Long * processes some cpu before returning.  The process is left runnable.
479f1c579b1SScott Long *
480f1c579b1SScott Long * <<<<<<<< EXPERIMENTAL, UNTESTED >>>>>>>>>>
481f1c579b1SScott Long * asleep(void *ident, int priority, const char *wmesg, int timo)
482f1c579b1SScott Long * asleep() - async sleep call.  Place process on wait queue and return
483f1c579b1SScott Long * immediately without blocking.  The process stays runnable until await()
484f1c579b1SScott Long * is called.  If ident is NULL, remove process from wait queue if it is still
485f1c579b1SScott Long * on one.
486f1c579b1SScott Long *
487f1c579b1SScott Long * Only the most recent sleep condition is effective when making successive
488f1c579b1SScott Long * calls to asleep() or when calling tsleep().
489f1c579b1SScott Long *
490f1c579b1SScott Long * The timeout, if any, is not initiated until await() is called.  The sleep
491f1c579b1SScott Long * priority, signal, and timeout is specified in the asleep() call but may be
492f1c579b1SScott Long * overriden in the await() call.
493f1c579b1SScott Long *
494f1c579b1SScott Long * <<<<<<<< EXPERIMENTAL, UNTESTED >>>>>>>>>>
495f1c579b1SScott Long *      :do background rebuilding
496f1c579b1SScott Long ***************************************************************************
497f1c579b1SScott Long */
498f1c579b1SScott Long VOID arcmsr_do_thread_works(VOID *arg)
499f1c579b1SScott Long {
500f1c579b1SScott Long 	PACB pACB=(PACB) arg;
501f1c579b1SScott Long 	ARCMSR_LOCK_INIT(&pACB->arcmsr_kthread_lock, "arcmsr kthread lock");
502f1c579b1SScott Long 
503f1c579b1SScott Long 	#if ARCMSR_DEBUG0
504f1c579b1SScott Long 	printf("arcmsr_do_thread_works................. \n");
505f1c579b1SScott Long 	#endif
506f1c579b1SScott Long 
507f1c579b1SScott Long 	ARCMSR_LOCK_ACQUIRE(&pACB->arcmsr_kthread_lock);
508f1c579b1SScott Long 	while(1)
509f1c579b1SScott Long 	{
510f1c579b1SScott Long 		tsleep((caddr_t)pACB->kthread_proc, PRIBIO | PWAIT, "arcmsr",  hz/4);/*.25 sec*/
511f1c579b1SScott Long 		/*
512f1c579b1SScott Long 		** if do_dpcQ_semaphore is signal
513f1c579b1SScott Long 		** do following works
514f1c579b1SScott Long 		*/
515f1c579b1SScott Long         arcmsr_do_dpcQ(pACB); /*see if there were some dpc routine need to execute*/
516f1c579b1SScott Long 		if(pACB->acb_flags & ACB_F_STOP_THREAD)
517f1c579b1SScott Long 		{
518f1c579b1SScott Long 			ARCMSR_LOCK_RELEASE(&pACB->arcmsr_kthread_lock);
519f1c579b1SScott Long 			break;
520f1c579b1SScott Long 		}
521f1c579b1SScott Long 	}
522f1c579b1SScott Long 	kthread_exit(0);
523f1c579b1SScott Long 	return;
524f1c579b1SScott Long }
525f1c579b1SScott Long /*
526f1c579b1SScott Long ************************************************************************
527f1c579b1SScott Long **
528f1c579b1SScott Long **
529f1c579b1SScott Long ************************************************************************
530f1c579b1SScott Long */
531f1c579b1SScott Long VOID arcmsr_flush_adapter_cache(PACB pACB)
532f1c579b1SScott Long {
533f1c579b1SScott Long     #if ARCMSR_DEBUG0
534f1c579b1SScott Long     printf("arcmsr_flush_adapter_cache..............\n");
535f1c579b1SScott Long     #endif
536f1c579b1SScott Long 	CHIP_REG_WRITE32(&pACB->pmu->inbound_msgaddr0,ARCMSR_INBOUND_MESG0_FLUSH_CACHE);
537f1c579b1SScott Long 	return;
538f1c579b1SScott Long }
539f1c579b1SScott Long /*
540f1c579b1SScott Long **********************************************************************
541f1c579b1SScott Long **
542f1c579b1SScott Long **
543f1c579b1SScott Long **
544f1c579b1SScott Long **********************************************************************
545f1c579b1SScott Long */
546f1c579b1SScott Long BOOLEAN arcmsr_wait_msgint_ready(PACB pACB)
547f1c579b1SScott Long {
548f1c579b1SScott Long 	ULONG Index;
549f1c579b1SScott Long 	UCHAR Retries=0x00;
550f1c579b1SScott Long 	do
551f1c579b1SScott Long 	{
552f1c579b1SScott Long 		for(Index=0; Index < 500000; Index++)
553f1c579b1SScott Long 		{
554f1c579b1SScott Long 			if(CHIP_REG_READ32(&pACB->pmu->outbound_intstatus) & ARCMSR_MU_OUTBOUND_MESSAGE0_INT)
555f1c579b1SScott Long 			{
556f1c579b1SScott Long 				CHIP_REG_WRITE32(&pACB->pmu->outbound_intstatus, ARCMSR_MU_OUTBOUND_MESSAGE0_INT);/*clear interrupt*/
557f1c579b1SScott Long 				return TRUE;
558f1c579b1SScott Long 			}
559f1c579b1SScott Long 			/* one us delay	*/
560f1c579b1SScott Long 			UDELAY(10);
561f1c579b1SScott Long 		}/*max 5 seconds*/
562f1c579b1SScott Long 	}while(Retries++ < 24);/*max 2 minutes*/
563f1c579b1SScott Long 	return FALSE;
564f1c579b1SScott Long }
565f1c579b1SScott Long /*
566f1c579b1SScott Long **********************************************************************
567f1c579b1SScott Long **
568f1c579b1SScott Long **  Q back this SRB into ACB ArraySRB
569f1c579b1SScott Long **
570f1c579b1SScott Long **********************************************************************
571f1c579b1SScott Long */
572f1c579b1SScott Long VOID arcmsr_srb_complete(PSRB pSRB)
573f1c579b1SScott Long {
574f1c579b1SScott Long 	ULONG s;
575f1c579b1SScott Long 	PACB pACB=pSRB->pACB;
576f1c579b1SScott Long     union ccb *pccb=pSRB->pccb;
577f1c579b1SScott Long 
578f1c579b1SScott Long 	#if ARCMSR_DEBUG0
579f1c579b1SScott Long 	printf("arcmsr_srb_complete: pSRB=%p srb_doneindex=%x srb_startindex=%x\n",pSRB,pACB->srb_doneindex,pACB->srb_startindex);
580f1c579b1SScott Long 	#endif
581f1c579b1SScott Long 
582f1c579b1SScott Long 	if ((pccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE)
583f1c579b1SScott Long 	{
584f1c579b1SScott Long 		bus_dmasync_op_t op;
585f1c579b1SScott Long 
586f1c579b1SScott Long 		if ((pccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)
587f1c579b1SScott Long 		{
588f1c579b1SScott Long 			op = BUS_DMASYNC_POSTREAD;
589f1c579b1SScott Long 		}
590f1c579b1SScott Long 		else
591f1c579b1SScott Long 		{
592f1c579b1SScott Long 			op = BUS_DMASYNC_POSTWRITE;
593f1c579b1SScott Long 		}
594f1c579b1SScott Long 		bus_dmamap_sync(pACB->buffer_dmat, pSRB->dmamap, op);
595f1c579b1SScott Long 		bus_dmamap_unload(pACB->buffer_dmat, pSRB->dmamap);
596f1c579b1SScott Long 	}
597f1c579b1SScott Long     s=splcam();
598f1c579b1SScott Long 	atomic_subtract_int(&pACB->srboutstandingcount,1);
599f1c579b1SScott Long 	pSRB->startdone=ARCMSR_SRB_DONE;
600f1c579b1SScott Long 	pSRB->srb_flags=0;
601f1c579b1SScott Long 	pACB->psrbringQ[pACB->srb_doneindex]=pSRB;
602f1c579b1SScott Long     pACB->srb_doneindex++;
603f1c579b1SScott Long     pACB->srb_doneindex %= ARCMSR_MAX_FREESRB_NUM;
604f1c579b1SScott Long     splx(s);
605f1c579b1SScott Long     xpt_done(pccb);
606f1c579b1SScott Long 	return;
607f1c579b1SScott Long }
608f1c579b1SScott Long /*
609f1c579b1SScott Long **********************************************************************
610f1c579b1SScott Long **       if scsi error do auto request sense
611f1c579b1SScott Long **********************************************************************
612f1c579b1SScott Long */
613f1c579b1SScott Long VOID arcmsr_report_SenseInfoBuffer(PSRB pSRB)
614f1c579b1SScott Long {
615f1c579b1SScott Long 	union ccb *pccb=pSRB->pccb;
616f1c579b1SScott Long 	PSENSE_DATA  psenseBuffer=(PSENSE_DATA)&pccb->csio.sense_data;
617f1c579b1SScott Long 	#if ARCMSR_DEBUG0
618f1c579b1SScott Long     printf("arcmsr_report_SenseInfoBuffer...........\n");
619f1c579b1SScott Long 	#endif
620f1c579b1SScott Long 
621f1c579b1SScott Long     pccb->ccb_h.status|=CAM_REQ_CMP;
622f1c579b1SScott Long     if(psenseBuffer)
623f1c579b1SScott Long 	{
624f1c579b1SScott Long 		memset(psenseBuffer, 0, sizeof(pccb->csio.sense_data));
625f1c579b1SScott Long 		memcpy(psenseBuffer,pSRB->arcmsr_cdb.SenseData,get_min(sizeof(struct _SENSE_DATA),sizeof(pccb->csio.sense_data)));
626f1c579b1SScott Long 	    psenseBuffer->ErrorCode=0x70;
627f1c579b1SScott Long         psenseBuffer->Valid=1;
628f1c579b1SScott Long 		pccb->ccb_h.status|=CAM_AUTOSNS_VALID;
629f1c579b1SScott Long     }
630f1c579b1SScott Long     return;
631f1c579b1SScott Long }
632f1c579b1SScott Long /*
633f1c579b1SScott Long *********************************************************************
634f1c579b1SScott Long ** to insert pSRB into tail of pACB wait exec srbQ
635f1c579b1SScott Long *********************************************************************
636f1c579b1SScott Long */
637f1c579b1SScott Long VOID arcmsr_queue_wait2go_srb(PACB pACB,PSRB pSRB)
638f1c579b1SScott Long {
639f1c579b1SScott Long     ULONG s;
640f1c579b1SScott Long 	LONG i=0;
641f1c579b1SScott Long     #if ARCMSR_DEBUG0
642f1c579b1SScott Long 	printf("arcmsr_qtail_wait2go_srb:......................................... \n");
643f1c579b1SScott Long     #endif
644f1c579b1SScott Long 
645f1c579b1SScott Long 	s=splcam();
646f1c579b1SScott Long 	while(1)
647f1c579b1SScott Long 	{
648f1c579b1SScott Long 		if(pACB->psrbwait2go[i]==NULL)
649f1c579b1SScott Long 		{
650f1c579b1SScott Long 			pACB->psrbwait2go[i]=pSRB;
651f1c579b1SScott Long         	atomic_add_int(&pACB->srbwait2gocount,1);
652f1c579b1SScott Long             splx(s);
653f1c579b1SScott Long 			return;
654f1c579b1SScott Long 		}
655f1c579b1SScott Long 		i++;
656f1c579b1SScott Long 		i%=ARCMSR_MAX_OUTSTANDING_CMD;
657f1c579b1SScott Long 	}
658f1c579b1SScott Long 	return;
659f1c579b1SScott Long }
660f1c579b1SScott Long /*
661f1c579b1SScott Long *********************************************************************
662f1c579b1SScott Long **
663f1c579b1SScott Long *********************************************************************
664f1c579b1SScott Long */
665f1c579b1SScott Long VOID arcmsr_abort_allcmd(PACB pACB)
666f1c579b1SScott Long {
667f1c579b1SScott Long 	CHIP_REG_WRITE32(&pACB->pmu->inbound_msgaddr0,ARCMSR_INBOUND_MESG0_ABORT_CMD);
668f1c579b1SScott Long 	return;
669f1c579b1SScott Long }
670f1c579b1SScott Long 
671f1c579b1SScott Long /*
672f1c579b1SScott Long ****************************************************************************
673f1c579b1SScott Long ** Routine Description: Reset 80331 iop.
674f1c579b1SScott Long **           Arguments:
675f1c579b1SScott Long **        Return Value: Nothing.
676f1c579b1SScott Long ****************************************************************************
677f1c579b1SScott Long */
678f1c579b1SScott Long VOID arcmsr_iop_reset(PACB pACB)
679f1c579b1SScott Long {
680f1c579b1SScott Long 	PSRB pSRB,pfreesrb;
681f1c579b1SScott Long 	ULONG intmask_org,mask;
682f1c579b1SScott Long     LONG i=0;
683f1c579b1SScott Long 
684f1c579b1SScott Long 	#if ARCMSR_DEBUG0
685f1c579b1SScott Long 	printf("arcmsr_iop_reset: reset iop controller......................................\n");
686f1c579b1SScott Long 	#endif
687f1c579b1SScott Long 	if(pACB->srboutstandingcount!=0)
688f1c579b1SScott Long 	{
689f1c579b1SScott Long 		/* Q back all outstanding srb into wait exec psrb Q*/
690f1c579b1SScott Long 		#if ARCMSR_DEBUG0
691f1c579b1SScott Long 		printf("arcmsr_iop_reset: srboutstandingcount=%d ...\n",pACB->srboutstandingcount);
692f1c579b1SScott Long 		#endif
693f1c579b1SScott Long         /* disable all outbound interrupt */
694f1c579b1SScott Long 		intmask_org=CHIP_REG_READ32(&pACB->pmu->outbound_intmask);
695f1c579b1SScott Long         CHIP_REG_WRITE32(&pACB->pmu->outbound_intmask,intmask_org|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE);
696f1c579b1SScott Long         /* talk to iop 331 outstanding command aborted*/
697f1c579b1SScott Long 		arcmsr_abort_allcmd(pACB);
698f1c579b1SScott Long 		if(arcmsr_wait_msgint_ready(pACB)!=TRUE)
699f1c579b1SScott Long 		{
700f1c579b1SScott Long             printf("arcmsr_iop_reset: wait 'abort all outstanding command' timeout.................in \n");
701f1c579b1SScott Long 		}
702f1c579b1SScott Long 		/*clear all outbound posted Q*/
703f1c579b1SScott Long 		for(i=0;i<ARCMSR_MAX_OUTSTANDING_CMD;i++)
704f1c579b1SScott Long 		{
705f1c579b1SScott Long 			CHIP_REG_READ32(&pACB->pmu->outbound_queueport);
706f1c579b1SScott Long 		}
707f1c579b1SScott Long 		pfreesrb=pACB->pfreesrb;
708f1c579b1SScott Long 		for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++)
709f1c579b1SScott Long 		{
710f1c579b1SScott Long 	    	pSRB=&pfreesrb[i];
711f1c579b1SScott Long 			if(pSRB->startdone==ARCMSR_SRB_START)
712f1c579b1SScott Long 			{
713f1c579b1SScott Long 				pSRB->startdone=ARCMSR_SRB_ABORTED;
714f1c579b1SScott Long                 pSRB->pccb->ccb_h.status=CAM_REQ_ABORTED;
715f1c579b1SScott Long                 arcmsr_srb_complete(pSRB);
716f1c579b1SScott Long 			}
717f1c579b1SScott Long 		}
718f1c579b1SScott Long 		/* enable all outbound interrupt */
719f1c579b1SScott Long 		mask=~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE|ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE|ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE);
720f1c579b1SScott Long         CHIP_REG_WRITE32(&pACB->pmu->outbound_intmask,intmask_org & mask);
721f1c579b1SScott Long 		atomic_set_int(&pACB->srboutstandingcount,0);
722f1c579b1SScott Long 		/* post abort all outstanding command message to RAID controller */
723f1c579b1SScott Long 	}
724f1c579b1SScott Long 	i=0;
725f1c579b1SScott Long 	while(pACB->srbwait2gocount > 0)
726f1c579b1SScott Long 	{
727f1c579b1SScott Long 		pSRB=pACB->psrbwait2go[i];
728f1c579b1SScott Long 		if(pSRB!=NULL)
729f1c579b1SScott Long 		{
730f1c579b1SScott Long 			#if ARCMSR_DEBUG0
731f1c579b1SScott Long 			printf("arcmsr_iop_reset:abort command... srbwait2gocount=%d ...\n",pACB->srbwait2gocount);
732f1c579b1SScott Long 			#endif
733f1c579b1SScott Long 		    pACB->psrbwait2go[i]=NULL;
734f1c579b1SScott Long             pSRB->startdone=ARCMSR_SRB_ABORTED;
735f1c579b1SScott Long 			pSRB->pccb->ccb_h.status=CAM_REQ_ABORTED;
736f1c579b1SScott Long             arcmsr_srb_complete(pSRB);
737f1c579b1SScott Long 			atomic_subtract_int(&pACB->srbwait2gocount,1);
738f1c579b1SScott Long 		}
739f1c579b1SScott Long 		i++;
740f1c579b1SScott Long 		i%=ARCMSR_MAX_OUTSTANDING_CMD;
741f1c579b1SScott Long 	}
742f1c579b1SScott Long 	return;
743f1c579b1SScott Long }
744f1c579b1SScott Long /*
745f1c579b1SScott Long **********************************************************************
746f1c579b1SScott Long **
747f1c579b1SScott Long ** PAGE_SIZE=4096 or 8192,PAGE_SHIFT=12
748f1c579b1SScott Long **********************************************************************
749f1c579b1SScott Long */
750f1c579b1SScott Long VOID arcmsr_build_srb(PSRB pSRB, bus_dma_segment_t *dm_segs, LONG nseg)
751f1c579b1SScott Long {
752f1c579b1SScott Long     PARCMSR_CDB pARCMSR_CDB=&pSRB->arcmsr_cdb;
753f1c579b1SScott Long 	PCHAR psge=(PCHAR)&pARCMSR_CDB->u;
754f1c579b1SScott Long 	ULONG address_lo,address_hi;
755f1c579b1SScott Long 	union ccb *pccb=pSRB->pccb;
756f1c579b1SScott Long 	struct ccb_scsiio *pcsio=&pccb->csio;
757f1c579b1SScott Long 	LONG arccdbsize=0x30;
758f1c579b1SScott Long 
759f1c579b1SScott Long 	#if ARCMSR_DEBUG0
760f1c579b1SScott Long 	printf("arcmsr_build_srb........................... \n");
761f1c579b1SScott Long 	#endif
762f1c579b1SScott Long 	memset(pARCMSR_CDB,0,sizeof(struct _ARCMSR_CDB));
763f1c579b1SScott Long     pARCMSR_CDB->Bus=0;
764f1c579b1SScott Long     pARCMSR_CDB->TargetID=pccb->ccb_h.target_id;
765f1c579b1SScott Long     pARCMSR_CDB->LUN=pccb->ccb_h.target_lun;
766f1c579b1SScott Long     pARCMSR_CDB->Function=1;
767f1c579b1SScott Long 	pARCMSR_CDB->CdbLength=(UCHAR)pcsio->cdb_len;
768f1c579b1SScott Long     pARCMSR_CDB->Context=(CPT2INT)pARCMSR_CDB;
769f1c579b1SScott Long 	bcopy(pcsio->cdb_io.cdb_bytes, pARCMSR_CDB->Cdb, pcsio->cdb_len);
770f1c579b1SScott Long 	if(nseg != 0)
771f1c579b1SScott Long 	{
772f1c579b1SScott Long 		PACB pACB=pSRB->pACB;
773f1c579b1SScott Long 		bus_dmasync_op_t   op;
774f1c579b1SScott Long 		LONG length,i,cdb_sgcount=0;
775f1c579b1SScott Long 
776f1c579b1SScott Long 		/* map stor port SG list to our iop SG List.*/
777f1c579b1SScott Long 		for(i=0;i<nseg;i++)
778f1c579b1SScott Long 		{
779f1c579b1SScott Long 			/* Get the physical address of the current data pointer */
780f1c579b1SScott Long 			length=(ULONG) dm_segs[i].ds_len;
781f1c579b1SScott Long             address_lo=dma_addr_lo32(dm_segs[i].ds_addr);
782f1c579b1SScott Long 			address_hi=dma_addr_hi32(dm_segs[i].ds_addr);
783f1c579b1SScott Long 			if(address_hi==0)
784f1c579b1SScott Long 			{
785f1c579b1SScott Long 				PSG32ENTRY pdma_sg=(PSG32ENTRY)psge;
786f1c579b1SScott Long 				pdma_sg->address=address_lo;
787f1c579b1SScott Long 				pdma_sg->length=length;
788f1c579b1SScott Long 				psge += sizeof(SG32ENTRY);
789f1c579b1SScott Long 				arccdbsize += sizeof(SG32ENTRY);
790f1c579b1SScott Long 			}
791f1c579b1SScott Long 			else
792f1c579b1SScott Long 			{
793f1c579b1SScott Long 				LONG sg64s_size=0,tmplength=length;
794f1c579b1SScott Long 
795f1c579b1SScott Long      			#if ARCMSR_DEBUG0
796f1c579b1SScott Long 				printf("arcmsr_build_srb: !!!!!!!!!!!......address_hi=%x.... \n",address_hi);
797f1c579b1SScott Long 				#endif
798f1c579b1SScott Long 				while(1)
799f1c579b1SScott Long 				{
800f1c579b1SScott Long 					LONG64 span4G,length0;
801f1c579b1SScott Long 					PSG64ENTRY pdma_sg=(PSG64ENTRY)psge;
802f1c579b1SScott Long 
803f1c579b1SScott Long 					span4G=(LONG64)address_lo + tmplength;
804f1c579b1SScott Long 					pdma_sg->addresshigh=address_hi;
805f1c579b1SScott Long 					pdma_sg->address=address_lo;
806f1c579b1SScott Long 					if(span4G > 0x100000000)
807f1c579b1SScott Long 					{
808f1c579b1SScott Long 						/*see if cross 4G boundary*/
809f1c579b1SScott Long 						length0=0x100000000-address_lo;
810f1c579b1SScott Long 						pdma_sg->length=(ULONG)length0|IS_SG64_ADDR;
811f1c579b1SScott Long 						address_hi=address_hi+1;
812f1c579b1SScott Long 						address_lo=0;
813f1c579b1SScott Long 						tmplength=tmplength-(LONG)length0;
814f1c579b1SScott Long 						sg64s_size += sizeof(SG64ENTRY);
815f1c579b1SScott Long 						psge += sizeof(SG64ENTRY);
816f1c579b1SScott Long 						cdb_sgcount++;
817f1c579b1SScott Long 					}
818f1c579b1SScott Long 					else
819f1c579b1SScott Long 					{
820f1c579b1SScott Long     					pdma_sg->length=tmplength|IS_SG64_ADDR;
821f1c579b1SScott Long 						sg64s_size += sizeof(SG64ENTRY);
822f1c579b1SScott Long 						psge += sizeof(SG64ENTRY);
823f1c579b1SScott Long 						break;
824f1c579b1SScott Long 					}
825f1c579b1SScott Long 				}
826f1c579b1SScott Long 				arccdbsize += sg64s_size;
827f1c579b1SScott Long 			}
828f1c579b1SScott Long 			cdb_sgcount++;
829f1c579b1SScott Long 		}
830f1c579b1SScott Long 		pARCMSR_CDB->sgcount=(UCHAR)cdb_sgcount;
831f1c579b1SScott Long 		pARCMSR_CDB->DataLength=pcsio->dxfer_len;
832f1c579b1SScott Long 		if( arccdbsize > 256)
833f1c579b1SScott Long 		{
834f1c579b1SScott Long 			pARCMSR_CDB->Flags|=ARCMSR_CDB_FLAG_SGL_BSIZE;
835f1c579b1SScott Long 		}
836f1c579b1SScott Long 		if((pccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)
837f1c579b1SScott Long 		{
838f1c579b1SScott Long 			op=BUS_DMASYNC_PREREAD;
839f1c579b1SScott Long 		}
840f1c579b1SScott Long 		else
841f1c579b1SScott Long 		{
842f1c579b1SScott Long 			op=BUS_DMASYNC_PREWRITE;
843f1c579b1SScott Long 			pARCMSR_CDB->Flags|=ARCMSR_CDB_FLAG_WRITE;
844f1c579b1SScott Long 			pSRB->srb_flags|=SRB_FLAG_WRITE;
845f1c579b1SScott Long 		}
846f1c579b1SScott Long     	bus_dmamap_sync(pACB->buffer_dmat, pSRB->dmamap, op);
847f1c579b1SScott Long 	}
848f1c579b1SScott Long 	#if ARCMSR_DEBUG0
849f1c579b1SScott Long 	printf("arcmsr_build_srb: pSRB=%p cmd=%x xferlength=%d arccdbsize=%d sgcount=%d\n",pSRB,pcsio->cdb_io.cdb_bytes[0],pARCMSR_CDB->DataLength,arccdbsize,pARCMSR_CDB->sgcount);
850f1c579b1SScott Long 	#endif
851f1c579b1SScott Long     return;
852f1c579b1SScott Long }
853f1c579b1SScott Long /*
854f1c579b1SScott Long **************************************************************************
855f1c579b1SScott Long **
856f1c579b1SScott Long **	arcmsr_post_srb - Send a protocol specific ARC send postcard to a AIOC .
857f1c579b1SScott Long **	handle: Handle of registered ARC protocol driver
858f1c579b1SScott Long **	adapter_id: AIOC unique identifier(integer)
859f1c579b1SScott Long **	pPOSTCARD_SEND: Pointer to ARC send postcard
860f1c579b1SScott Long **
861f1c579b1SScott Long **	This routine posts a ARC send postcard to the request post FIFO of a
862f1c579b1SScott Long **	specific ARC adapter.
863f1c579b1SScott Long **
864f1c579b1SScott Long **************************************************************************
865f1c579b1SScott Long */
866f1c579b1SScott Long static VOID arcmsr_post_srb(PACB pACB,PSRB pSRB)
867f1c579b1SScott Long {
868f1c579b1SScott Long 	ULONG cdb_shifted_phyaddr=(ULONG) pSRB->cdb_shifted_phyaddr;
869f1c579b1SScott Long 	PARCMSR_CDB pARCMSR_CDB=(PARCMSR_CDB)&pSRB->arcmsr_cdb;
870f1c579b1SScott Long 
871f1c579b1SScott Long 	#if ARCMSR_DEBUG0
872f1c579b1SScott Long 	printf("arcmsr_post_srb: pSRB=%p  cdb_shifted_phyaddr=%x\n",pSRB,cdb_shifted_phyaddr);
873f1c579b1SScott Long 	#endif
874f1c579b1SScott Long     atomic_add_int(&pACB->srboutstandingcount,1);
875f1c579b1SScott Long 	pSRB->startdone=ARCMSR_SRB_START;
876f1c579b1SScott Long 	if(pARCMSR_CDB->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE)
877f1c579b1SScott Long 	{
878f1c579b1SScott Long 	    CHIP_REG_WRITE32(&pACB->pmu->inbound_queueport,cdb_shifted_phyaddr|ARCMSR_SRBPOST_FLAG_SGL_BSIZE);
879f1c579b1SScott Long 	}
880f1c579b1SScott Long 	else
881f1c579b1SScott Long 	{
882f1c579b1SScott Long 	    CHIP_REG_WRITE32(&pACB->pmu->inbound_queueport,cdb_shifted_phyaddr);
883f1c579b1SScott Long 	}
884f1c579b1SScott Long 	return;
885f1c579b1SScott Long }
886f1c579b1SScott Long /*
887f1c579b1SScott Long **************************************************************************
888f1c579b1SScott Long **
889f1c579b1SScott Long **
890f1c579b1SScott Long **************************************************************************
891f1c579b1SScott Long */
892f1c579b1SScott Long VOID arcmsr_post_wait2go_srb(PACB pACB)
893f1c579b1SScott Long {
894f1c579b1SScott Long 	ULONG s;
895f1c579b1SScott Long 	PSRB pSRB;
896f1c579b1SScott Long 	LONG i=0;
897f1c579b1SScott Long 	#if ARCMSR_DEBUG0
898f1c579b1SScott Long 	printf("arcmsr_post_wait2go_srb:srbwait2gocount=%d srboutstandingcount=%d\n",pACB->srbwait2gocount,pACB->srboutstandingcount);
899f1c579b1SScott Long 	#endif
900f1c579b1SScott Long     s=splcam();
901f1c579b1SScott Long 	while((pACB->srbwait2gocount > 0) && (pACB->srboutstandingcount < ARCMSR_MAX_OUTSTANDING_CMD))
902f1c579b1SScott Long 	{
903f1c579b1SScott Long 		pSRB=pACB->psrbwait2go[i];
904f1c579b1SScott Long 		if(pSRB!=NULL)
905f1c579b1SScott Long 		{
906f1c579b1SScott Long 			pACB->psrbwait2go[i]=NULL;
907f1c579b1SScott Long 			arcmsr_post_srb(pACB,pSRB);
908f1c579b1SScott Long 			atomic_subtract_int(&pACB->srbwait2gocount,1);
909f1c579b1SScott Long 		}
910f1c579b1SScott Long 		i++;
911f1c579b1SScott Long 		i%=ARCMSR_MAX_OUTSTANDING_CMD;
912f1c579b1SScott Long 	}
913f1c579b1SScott Long 	splx(s);
914f1c579b1SScott Long 	return;
915f1c579b1SScott Long }
916f1c579b1SScott Long /*
917f1c579b1SScott Long **********************************************************************
918f1c579b1SScott Long **   Function: arcmsr_post_Qbuffer
919f1c579b1SScott Long **     Output:
920f1c579b1SScott Long **********************************************************************
921f1c579b1SScott Long */
922f1c579b1SScott Long VOID arcmsr_post_Qbuffer(PACB pACB)
923f1c579b1SScott Long {
924f1c579b1SScott Long     ULONG s;
925f1c579b1SScott Long 	PUCHAR pQbuffer;
926f1c579b1SScott Long 	PQBUFFER pwbuffer=(PQBUFFER)&pACB->pmu->ioctl_wbuffer;
927f1c579b1SScott Long     PUCHAR iop_data=(PUCHAR)pwbuffer->data;
928f1c579b1SScott Long 	LONG allxfer_len=0;
929f1c579b1SScott Long 
930f1c579b1SScott Long     s=splcam();
931f1c579b1SScott Long 	while((pACB->wqbuf_firstindex!=pACB->wqbuf_lastindex) && (allxfer_len<124))
932f1c579b1SScott Long 	{
933f1c579b1SScott Long 		pQbuffer=&pACB->wqbuffer[pACB->wqbuf_firstindex];
934f1c579b1SScott Long 		memcpy(iop_data,pQbuffer,1);
935f1c579b1SScott Long 		pACB->wqbuf_firstindex++;
936f1c579b1SScott Long 		pACB->wqbuf_firstindex %= ARCMSR_MAX_QBUFFER; /*if last index number set it to 0 */
937f1c579b1SScott Long 		iop_data++;
938f1c579b1SScott Long 		allxfer_len++;
939f1c579b1SScott Long 	}
940f1c579b1SScott Long 	pwbuffer->data_len=allxfer_len;
941f1c579b1SScott Long 	/*
942f1c579b1SScott Long 	** push inbound doorbell and wait reply at hwinterrupt routine for next Qbuffer post
943f1c579b1SScott Long 	*/
944f1c579b1SScott Long  	CHIP_REG_WRITE32(&pACB->pmu->inbound_doorbell,ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK);
945f1c579b1SScott Long 	splx(s);
946f1c579b1SScott Long 	return;
947f1c579b1SScott Long }
948f1c579b1SScott Long /*
949f1c579b1SScott Long ************************************************************************
950f1c579b1SScott Long **
951f1c579b1SScott Long **
952f1c579b1SScott Long ************************************************************************
953f1c579b1SScott Long */
954f1c579b1SScott Long VOID arcmsr_stop_adapter_bgrb(PACB pACB)
955f1c579b1SScott Long {
956f1c579b1SScott Long     #if ARCMSR_DEBUG0
957f1c579b1SScott Long     printf("arcmsr_stop_adapter_bgrb..............\n");
958f1c579b1SScott Long     #endif
959f1c579b1SScott Long 	pACB->acb_flags |= ACB_F_MSG_STOP_BGRB;
960f1c579b1SScott Long 	pACB->acb_flags &= ~ACB_F_MSG_START_BGRB;
961f1c579b1SScott Long 	CHIP_REG_WRITE32(&pACB->pmu->inbound_msgaddr0,ARCMSR_INBOUND_MESG0_STOP_BGRB);
962f1c579b1SScott Long 	return;
963f1c579b1SScott Long }
964f1c579b1SScott Long /*
965f1c579b1SScott Long ************************************************************************
966f1c579b1SScott Long **
967f1c579b1SScott Long **
968f1c579b1SScott Long ************************************************************************
969f1c579b1SScott Long */
970f1c579b1SScott Long static VOID arcmsr_poll(struct cam_sim * psim)
971f1c579b1SScott Long {
972f1c579b1SScott Long 	arcmsr_interrupt(cam_sim_softc(psim));
973f1c579b1SScott Long 	return;
974f1c579b1SScott Long }
975f1c579b1SScott Long /*
976f1c579b1SScott Long **********************************************************************
977f1c579b1SScott Long **   Function:  arcmsr_interrupt
978f1c579b1SScott Long **     Output:  VOID
979f1c579b1SScott Long **   CAM  Status field values
980f1c579b1SScott Long **typedef enum {
981f1c579b1SScott Long **	CAM_REQ_INPROG,		   CCB request is in progress
982f1c579b1SScott Long **	CAM_REQ_CMP,		   CCB request completed without error
983f1c579b1SScott Long **	CAM_REQ_ABORTED,	   CCB request aborted by the host
984f1c579b1SScott Long **	CAM_UA_ABORT,		   Unable to abort CCB request
985f1c579b1SScott Long **	CAM_REQ_CMP_ERR,	   CCB request completed with an error
986f1c579b1SScott Long **	CAM_BUSY,		       CAM subsytem is busy
987f1c579b1SScott Long **	CAM_REQ_INVALID,	   CCB request was invalid
988f1c579b1SScott Long **	CAM_PATH_INVALID,	   Supplied Path ID is invalid
989f1c579b1SScott Long **	CAM_DEV_NOT_THERE,	   SCSI Device Not Installed/there
990f1c579b1SScott Long **	CAM_UA_TERMIO,		   Unable to terminate I/O CCB request
991f1c579b1SScott Long **	CAM_SEL_TIMEOUT,	   Target Selection Timeout
992f1c579b1SScott Long **	CAM_CMD_TIMEOUT,	   Command timeout
993f1c579b1SScott Long **	CAM_SCSI_STATUS_ERROR,	   SCSI error, look at error code in CCB
994f1c579b1SScott Long **	CAM_MSG_REJECT_REC,	   Message Reject Received
995f1c579b1SScott Long **	CAM_SCSI_BUS_RESET,	   SCSI Bus Reset Sent/Received
996f1c579b1SScott Long **	CAM_UNCOR_PARITY,	   Uncorrectable parity error occurred
997f1c579b1SScott Long **	CAM_AUTOSENSE_FAIL=0x10,   Autosense: request sense cmd fail
998f1c579b1SScott Long **	CAM_NO_HBA,		   No HBA Detected error
999f1c579b1SScott Long **	CAM_DATA_RUN_ERR,	   Data Overrun error
1000f1c579b1SScott Long **	CAM_UNEXP_BUSFREE,	   Unexpected Bus Free
1001f1c579b1SScott Long **	CAM_SEQUENCE_FAIL,	   Target Bus Phase Sequence Failure
1002f1c579b1SScott Long **	CAM_CCB_LEN_ERR,	   CCB length supplied is inadequate
1003f1c579b1SScott Long **	CAM_PROVIDE_FAIL,	   Unable to provide requested capability
1004f1c579b1SScott Long **	CAM_BDR_SENT,		   A SCSI BDR msg was sent to target
1005f1c579b1SScott Long **	CAM_REQ_TERMIO,		   CCB request terminated by the host
1006f1c579b1SScott Long **	CAM_UNREC_HBA_ERROR,	   Unrecoverable Host Bus Adapter Error
1007f1c579b1SScott Long **	CAM_REQ_TOO_BIG,	   The request was too large for this host
1008f1c579b1SScott Long **	CAM_REQUEUE_REQ,
1009f1c579b1SScott Long **				 * This request should be requeued to preserve
1010f1c579b1SScott Long **				 * transaction ordering.  This typically occurs
1011f1c579b1SScott Long **				 * when the SIM recognizes an error that should
1012f1c579b1SScott Long **				 * freeze the queue and must place additional
1013f1c579b1SScott Long **				 * requests for the target at the sim level
1014f1c579b1SScott Long **				 * back into the XPT queue.
1015f1c579b1SScott Long **
1016f1c579b1SScott Long **	CAM_IDE=0x33,		   Initiator Detected Error
1017f1c579b1SScott Long **	CAM_RESRC_UNAVAIL,	   Resource Unavailable
1018f1c579b1SScott Long **	CAM_UNACKED_EVENT,	   Unacknowledged Event by Host
1019f1c579b1SScott Long **	CAM_MESSAGE_RECV,	   Message Received in Host Target Mode
1020f1c579b1SScott Long **	CAM_INVALID_CDB,	   Invalid CDB received in Host Target Mode
1021f1c579b1SScott Long **	CAM_LUN_INVALID,	   Lun supplied is invalid
1022f1c579b1SScott Long **	CAM_TID_INVALID,	   Target ID supplied is invalid
1023f1c579b1SScott Long **	CAM_FUNC_NOTAVAIL,	   The requested function is not available
1024f1c579b1SScott Long **	CAM_NO_NEXUS,		   Nexus is not established
1025f1c579b1SScott Long **	CAM_IID_INVALID,	   The initiator ID is invalid
1026f1c579b1SScott Long **	CAM_CDB_RECVD,		   The SCSI CDB has been received
1027f1c579b1SScott Long **	CAM_LUN_ALRDY_ENA,	   The LUN is already eanbeld for target mode
1028f1c579b1SScott Long **	CAM_SCSI_BUSY,		   SCSI Bus Busy
1029f1c579b1SScott Long **
1030f1c579b1SScott Long **	CAM_DEV_QFRZN=0x40,	   The DEV queue is frozen w/this err
1031f1c579b1SScott Long **
1032f1c579b1SScott Long **				   Autosense data valid for target
1033f1c579b1SScott Long **	CAM_AUTOSNS_VALID=0x80,
1034f1c579b1SScott Long **	CAM_RELEASE_SIMQ=0x100,   SIM ready to take more commands
1035f1c579b1SScott Long **	CAM_SIM_QUEUED  =0x200,   SIM has this command in it's queue
1036f1c579b1SScott Long **
1037f1c579b1SScott Long **	CAM_STATUS_MASK=0x3F,	   Mask bits for just the status #
1038f1c579b1SScott Long **
1039f1c579b1SScott Long **				   Target Specific Adjunct Status
1040f1c579b1SScott Long **	CAM_SENT_SENSE=0x40000000	   sent sense with status
1041f1c579b1SScott Long **} cam_status;
1042f1c579b1SScott Long **********************************************************************
1043f1c579b1SScott Long */
1044f1c579b1SScott Long static VOID arcmsr_interrupt(VOID *arg)
1045f1c579b1SScott Long {
1046f1c579b1SScott Long 	PACB pACB=(PACB)arg;
1047f1c579b1SScott Long 	PSRB pSRB;
1048f1c579b1SScott Long 	ULONG flagpsrb,outbound_intstatus,outbound_doorbell;
1049f1c579b1SScott Long 
1050f1c579b1SScott Long     #if ARCMSR_DEBUG0
1051f1c579b1SScott Long     printf("arcmsr_interrupt..............\n");
1052f1c579b1SScott Long     #endif
1053f1c579b1SScott Long 	/*
1054f1c579b1SScott Long 	*********************************************
1055f1c579b1SScott Long 	**   check outbound intstatus �˹�L�l�t�����a
1056f1c579b1SScott Long 	*********************************************
1057f1c579b1SScott Long 	*/
1058f1c579b1SScott Long 	outbound_intstatus=CHIP_REG_READ32(&pACB->pmu->outbound_intstatus) & pACB->outbound_int_enable;
1059f1c579b1SScott Long     CHIP_REG_WRITE32(&pACB->pmu->outbound_intstatus, outbound_intstatus);/*clear interrupt*/
1060f1c579b1SScott Long 	if(outbound_intstatus & ARCMSR_MU_OUTBOUND_DOORBELL_INT)
1061f1c579b1SScott Long 	{
1062f1c579b1SScott Long 		#if ARCMSR_DEBUG0
1063f1c579b1SScott Long 		printf("arcmsr_interrupt:..........ARCMSR_MU_OUTBOUND_DOORBELL_INT\n");
1064f1c579b1SScott Long 		#endif
1065f1c579b1SScott Long 		/*
1066f1c579b1SScott Long 		*********************************************
1067f1c579b1SScott Long 		**  DOORBELL �m��! �O�_���l��nñ��
1068f1c579b1SScott Long 		*********************************************
1069f1c579b1SScott Long 		*/
1070f1c579b1SScott Long 		outbound_doorbell=CHIP_REG_READ32(&pACB->pmu->outbound_doorbell);
1071f1c579b1SScott Long 		CHIP_REG_WRITE32(&pACB->pmu->outbound_doorbell,outbound_doorbell);/*clear interrupt */
1072f1c579b1SScott Long 		if(outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_WRITE_OK)
1073f1c579b1SScott Long 		{
1074f1c579b1SScott Long 			PQBUFFER prbuffer=(PQBUFFER)&pACB->pmu->ioctl_rbuffer;
1075f1c579b1SScott Long 			PUCHAR iop_data=(PUCHAR)prbuffer->data;
1076f1c579b1SScott Long 			PUCHAR pQbuffer;
1077f1c579b1SScott Long 			LONG my_empty_len,iop_len,rqbuf_firstindex,rqbuf_lastindex;
1078f1c579b1SScott Long 			ULONG s;
1079f1c579b1SScott Long             /*check this iop data if overflow my rqbuffer*/
1080f1c579b1SScott Long             s=splcam();
1081f1c579b1SScott Long 			rqbuf_lastindex=pACB->rqbuf_lastindex;
1082f1c579b1SScott Long 			rqbuf_firstindex=pACB->rqbuf_firstindex;
1083f1c579b1SScott Long 			iop_len=prbuffer->data_len;
1084f1c579b1SScott Long             my_empty_len=(rqbuf_firstindex-rqbuf_lastindex-1)&(ARCMSR_MAX_QBUFFER-1);
1085f1c579b1SScott Long 			if(my_empty_len>=iop_len)
1086f1c579b1SScott Long 			{
1087f1c579b1SScott Long 				while(iop_len > 0)
1088f1c579b1SScott Long 				{
1089f1c579b1SScott Long 					pQbuffer=&pACB->rqbuffer[pACB->rqbuf_lastindex];
1090f1c579b1SScott Long 					memcpy(pQbuffer,iop_data,1);
1091f1c579b1SScott Long 					pACB->rqbuf_lastindex++;
1092f1c579b1SScott Long 					pACB->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER;/*if last index number set it to 0 */
1093f1c579b1SScott Long 					iop_data++;
1094f1c579b1SScott Long 					iop_len--;
1095f1c579b1SScott Long 				}
1096f1c579b1SScott Long 				CHIP_REG_WRITE32(&pACB->pmu->inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK);/*signature, let IOP331 know data has been readed */
1097f1c579b1SScott Long 			}
1098f1c579b1SScott Long 			else
1099f1c579b1SScott Long 			{
1100f1c579b1SScott Long 				pACB->acb_flags|=ACB_F_IOPDATA_OVERFLOW;
1101f1c579b1SScott Long 			}
1102f1c579b1SScott Long 			splx(s);
1103f1c579b1SScott Long 		}
1104f1c579b1SScott Long 		if(outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_READ_OK)
1105f1c579b1SScott Long 		{
1106f1c579b1SScott Long 			ULONG s;
1107f1c579b1SScott Long 			/*
1108f1c579b1SScott Long 			*********************************************
1109f1c579b1SScott Long 			**           �ݬݬO�_�٦��l��n���D�H�X
1110f1c579b1SScott Long 			*********************************************
1111f1c579b1SScott Long 			*/
1112f1c579b1SScott Long 			s=splcam();
1113f1c579b1SScott Long 			if(pACB->wqbuf_firstindex!=pACB->wqbuf_lastindex)
1114f1c579b1SScott Long 			{
1115f1c579b1SScott Long 				PUCHAR pQbuffer;
1116f1c579b1SScott Long 				PQBUFFER pwbuffer=(PQBUFFER)&pACB->pmu->ioctl_wbuffer;
1117f1c579b1SScott Long 				PUCHAR iop_data=(PUCHAR)pwbuffer->data;
1118f1c579b1SScott Long 				LONG allxfer_len=0;
1119f1c579b1SScott Long 
1120f1c579b1SScott Long 				while((pACB->wqbuf_firstindex!=pACB->wqbuf_lastindex) && (allxfer_len<124))
1121f1c579b1SScott Long 				{
1122f1c579b1SScott Long 					pQbuffer=&pACB->wqbuffer[pACB->wqbuf_firstindex];
1123f1c579b1SScott Long    					memcpy(iop_data,pQbuffer,1);
1124f1c579b1SScott Long 					pACB->wqbuf_firstindex++;
1125f1c579b1SScott Long 					pACB->wqbuf_firstindex %= ARCMSR_MAX_QBUFFER; /*if last index number set it to 0 */
1126f1c579b1SScott Long 					iop_data++;
1127f1c579b1SScott Long 					allxfer_len++;
1128f1c579b1SScott Long 				}
1129f1c579b1SScott Long 				pwbuffer->data_len=allxfer_len;
1130f1c579b1SScott Long 				/*
1131f1c579b1SScott Long 				** push inbound doorbell tell iop driver data write ok and wait reply on next hwinterrupt for next Qbuffer post
1132f1c579b1SScott Long 				*/
1133f1c579b1SScott Long 				CHIP_REG_WRITE32(&pACB->pmu->inbound_doorbell,ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK);
1134f1c579b1SScott Long  			}
1135f1c579b1SScott Long 			else
1136f1c579b1SScott Long 			{
1137f1c579b1SScott Long 				pACB->acb_flags |= ACB_F_IOCTL_WQBUFFER_CLEARED;
1138f1c579b1SScott Long 			}
1139f1c579b1SScott Long 			splx(s);
1140f1c579b1SScott Long 		}
1141f1c579b1SScott Long 	}
1142f1c579b1SScott Long 	if(outbound_intstatus & ARCMSR_MU_OUTBOUND_POSTQUEUE_INT)
1143f1c579b1SScott Long 	{
1144f1c579b1SScott Long  		/*
1145f1c579b1SScott Long 		*****************************************************************************
1146f1c579b1SScott Long 		**               areca cdb command done
1147f1c579b1SScott Long 		*****************************************************************************
1148f1c579b1SScott Long 		*/
1149f1c579b1SScott Long 		while(1)
1150f1c579b1SScott Long 		{
1151f1c579b1SScott Long 			if((flagpsrb=CHIP_REG_READ32(&pACB->pmu->outbound_queueport)) == 0xFFFFFFFF)
1152f1c579b1SScott Long 			{
1153f1c579b1SScott Long 				break;/*chip FIFO no srb for completion already*/
1154f1c579b1SScott Long 			}
1155f1c579b1SScott Long 			/* check if command done with no error*/
1156f1c579b1SScott Long 			pSRB=(PSRB)(CINT2P)(pACB->vir2phy_offset+(flagpsrb << 5));/*frame must be 32 bytes aligned*/
1157f1c579b1SScott Long 			if((pSRB->pACB!=pACB) || (pSRB->startdone!=ARCMSR_SRB_START))
1158f1c579b1SScott Long 			{
1159f1c579b1SScott Long 				if(pSRB->startdone==ARCMSR_SRB_ABORTED)
1160f1c579b1SScott Long 				{
1161f1c579b1SScott Long 					pSRB->pccb->ccb_h.status=CAM_REQ_ABORTED;
1162f1c579b1SScott Long 					arcmsr_srb_complete(pSRB);
1163f1c579b1SScott Long 					break;
1164f1c579b1SScott Long 				}
1165f1c579b1SScott Long   				printf("arcmsr_interrupt:got an illegal srb command done ...pACB=%p pSRB=%p srboutstandingcount=%d .....\n",pACB,pSRB,pACB->srboutstandingcount);
1166f1c579b1SScott Long 				break;
1167f1c579b1SScott Long 			}
1168f1c579b1SScott Long 			if((flagpsrb & ARCMSR_SRBREPLY_FLAG_ERROR)==0)
1169f1c579b1SScott Long 			{
1170f1c579b1SScott Long 				pSRB->pccb->ccb_h.status=CAM_REQ_CMP;
1171f1c579b1SScott Long 				arcmsr_srb_complete(pSRB);
1172f1c579b1SScott Long 			}
1173f1c579b1SScott Long 			else
1174f1c579b1SScott Long 			{
1175f1c579b1SScott Long 				switch(pSRB->arcmsr_cdb.DeviceStatus)
1176f1c579b1SScott Long 				{
1177f1c579b1SScott Long 				case ARCMSR_DEV_SELECT_TIMEOUT:
1178f1c579b1SScott Long 					{
1179f1c579b1SScott Long 						#if ARCMSR_DEBUG0
1180f1c579b1SScott Long 						printf("pSRB=%p ......ARCMSR_DEV_SELECT_TIMEOUT\n",pSRB);
1181f1c579b1SScott Long 						#endif
1182f1c579b1SScott Long  						pSRB->pccb->ccb_h.status=CAM_SEL_TIMEOUT;
1183f1c579b1SScott Long 						arcmsr_srb_complete(pSRB);
1184f1c579b1SScott Long 					}
1185f1c579b1SScott Long 					break;
1186f1c579b1SScott Long 				case ARCMSR_DEV_ABORTED:
1187f1c579b1SScott Long 					{
1188f1c579b1SScott Long 						#if ARCMSR_DEBUG0
1189f1c579b1SScott Long 						printf("pSRB=%p ......ARCMSR_DEV_ABORTED\n",pSRB);
1190f1c579b1SScott Long 						#endif
1191f1c579b1SScott Long 						pSRB->pccb->ccb_h.status=CAM_DEV_NOT_THERE;
1192f1c579b1SScott Long 						arcmsr_srb_complete(pSRB);
1193f1c579b1SScott Long 					}
1194f1c579b1SScott Long 					break;
1195f1c579b1SScott Long 				case ARCMSR_DEV_INIT_FAIL:
1196f1c579b1SScott Long 					{
1197f1c579b1SScott Long 						#if ARCMSR_DEBUG0
1198f1c579b1SScott Long 						printf("pSRB=%p .....ARCMSR_DEV_INIT_FAIL\n",pSRB);
1199f1c579b1SScott Long 						#endif
1200f1c579b1SScott Long  						pSRB->pccb->ccb_h.status=CAM_DEV_NOT_THERE;
1201f1c579b1SScott Long 						arcmsr_srb_complete(pSRB);
1202f1c579b1SScott Long 					}
1203f1c579b1SScott Long 					break;
1204f1c579b1SScott Long 				case SCSISTAT_CHECK_CONDITION:
1205f1c579b1SScott Long 					{
1206f1c579b1SScott Long 						#if ARCMSR_DEBUG0
1207f1c579b1SScott Long 						printf("pSRB=%p .....SCSISTAT_CHECK_CONDITION\n",pSRB);
1208f1c579b1SScott Long 						#endif
1209f1c579b1SScott Long                         arcmsr_report_SenseInfoBuffer(pSRB);
1210f1c579b1SScott Long 						arcmsr_srb_complete(pSRB);
1211f1c579b1SScott Long 					}
1212f1c579b1SScott Long 					break;
1213f1c579b1SScott Long 				default:
1214f1c579b1SScott Long 					/* error occur Q all error srb to errorsrbpending Q*/
1215f1c579b1SScott Long  					printf("arcmsr_interrupt:command error done ......but got unknow DeviceStatus=%x....\n",pSRB->arcmsr_cdb.DeviceStatus);
1216f1c579b1SScott Long 					pSRB->pccb->ccb_h.status=CAM_UNCOR_PARITY;/*unknow error or crc error just for retry*/
1217f1c579b1SScott Long 					arcmsr_srb_complete(pSRB);
1218f1c579b1SScott Long 					break;
1219f1c579b1SScott Long 				}
1220f1c579b1SScott Long 			}
1221f1c579b1SScott Long 		}	/*drain reply FIFO*/
1222f1c579b1SScott Long 	}
1223f1c579b1SScott Long 	if(pACB->srbwait2gocount != 0)
1224f1c579b1SScott Long 	{
1225f1c579b1SScott Long     	arcmsr_post_wait2go_srb(pACB);/*try to post all pending srb*/
1226f1c579b1SScott Long  	}
1227f1c579b1SScott Long 	return;
1228f1c579b1SScott Long }
1229f1c579b1SScott Long /*
1230f1c579b1SScott Long ***********************************************************************
1231f1c579b1SScott Long **
1232f1c579b1SScott Long **int	copyin __P((const void *udaddr, void *kaddr, size_t len));
1233f1c579b1SScott Long **int	copyout __P((const void *kaddr, void *udaddr, size_t len));
1234f1c579b1SScott Long **
1235f1c579b1SScott Long **ENOENT     "" No such file or directory ""
1236f1c579b1SScott Long **ENOIOCTL   "" ioctl not handled by this layer ""
1237f1c579b1SScott Long **ENOMEM     "" Cannot allocate memory ""
1238f1c579b1SScott Long **EINVAL     "" Invalid argument ""
1239f1c579b1SScott Long ************************************************************************
1240f1c579b1SScott Long */
1241f1c579b1SScott Long LONG arcmsr_iop_ioctlcmd(PACB pACB,ULONG ioctl_cmd,caddr_t arg)
1242f1c579b1SScott Long {
1243f1c579b1SScott Long 	PCMD_IO_CONTROL pccbioctl=(PCMD_IO_CONTROL) arg;
1244f1c579b1SScott Long 
1245f1c579b1SScott Long  	#if ARCMSR_DEBUG0
1246f1c579b1SScott Long 	printf("arcmsr_iop_ioctlcmd................. \n");
1247f1c579b1SScott Long 	#endif
1248f1c579b1SScott Long 
1249f1c579b1SScott Long 	if(memcmp(pccbioctl->Signature,"ARCMSR",6)!=0)
1250f1c579b1SScott Long     {
1251f1c579b1SScott Long         return EINVAL;
1252f1c579b1SScott Long 	}
1253f1c579b1SScott Long 	switch(ioctl_cmd)
1254f1c579b1SScott Long 	{
1255f1c579b1SScott Long 	case ARCMSR_IOCTL_READ_RQBUFFER:
1256f1c579b1SScott Long 		{
1257f1c579b1SScott Long 			ULONG s;
1258f1c579b1SScott Long 			PCMD_IOCTL_FIELD pccbioctlfld=(PCMD_IOCTL_FIELD)arg;
1259f1c579b1SScott Long 			PUCHAR pQbuffer,ptmpQbuffer=pccbioctlfld->ioctldatabuffer;
1260f1c579b1SScott Long 			LONG allxfer_len=0;
1261f1c579b1SScott Long 
1262f1c579b1SScott Long             s=splcam();
1263f1c579b1SScott Long 			while((pACB->rqbuf_firstindex!=pACB->rqbuf_lastindex) && (allxfer_len<1031))
1264f1c579b1SScott Long 			{
1265f1c579b1SScott Long 				/*copy READ QBUFFER to srb*/
1266f1c579b1SScott Long                 pQbuffer=&pACB->rqbuffer[pACB->rqbuf_firstindex];
1267f1c579b1SScott Long 				memcpy(ptmpQbuffer,pQbuffer,1);
1268f1c579b1SScott Long 				pACB->rqbuf_firstindex++;
1269f1c579b1SScott Long 				pACB->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER; /*if last index number set it to 0 */
1270f1c579b1SScott Long 				ptmpQbuffer++;
1271f1c579b1SScott Long 				allxfer_len++;
1272f1c579b1SScott Long 			}
1273f1c579b1SScott Long 			if(pACB->acb_flags & ACB_F_IOPDATA_OVERFLOW)
1274f1c579b1SScott Long 			{
1275f1c579b1SScott Long                 PQBUFFER prbuffer=(PQBUFFER)&pACB->pmu->ioctl_rbuffer;
1276f1c579b1SScott Long                 PUCHAR pQbuffer;
1277f1c579b1SScott Long 				PUCHAR iop_data=(PUCHAR)prbuffer->data;
1278f1c579b1SScott Long                 LONG iop_len;
1279f1c579b1SScott Long 
1280f1c579b1SScott Long                 pACB->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
1281f1c579b1SScott Long 			    iop_len=(LONG)prbuffer->data_len;
1282f1c579b1SScott Long 				/*this iop data does no chance to make me overflow again here, so just do it*/
1283f1c579b1SScott Long 				while(iop_len>0)
1284f1c579b1SScott Long 				{
1285f1c579b1SScott Long                     pQbuffer=&pACB->rqbuffer[pACB->rqbuf_lastindex];
1286f1c579b1SScott Long 					memcpy(pQbuffer,iop_data,1);
1287f1c579b1SScott Long 					pACB->rqbuf_lastindex++;
1288f1c579b1SScott Long 					pACB->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER;/*if last index number set it to 0 */
1289f1c579b1SScott Long 					iop_data++;
1290f1c579b1SScott Long 					iop_len--;
1291f1c579b1SScott Long 				}
1292f1c579b1SScott Long 				CHIP_REG_WRITE32(&pACB->pmu->inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK);/*signature, let IOP331 know data has been readed */
1293f1c579b1SScott Long 			}
1294f1c579b1SScott Long 			pccbioctl->Length=allxfer_len;
1295f1c579b1SScott Long 			pccbioctl->ReturnCode=ARCMSR_IOCTL_RETURNCODE_OK;
1296f1c579b1SScott Long 			splx(s);
1297f1c579b1SScott Long 			return ARC_IOCTL_SUCCESS;
1298f1c579b1SScott Long  		}
1299f1c579b1SScott Long 		break;
1300f1c579b1SScott Long 	case ARCMSR_IOCTL_WRITE_WQBUFFER:
1301f1c579b1SScott Long 		{
1302f1c579b1SScott Long 			ULONG s;
1303f1c579b1SScott Long             PCMD_IOCTL_FIELD pccbioctlfld=(PCMD_IOCTL_FIELD)arg;
1304f1c579b1SScott Long 			LONG my_empty_len,user_len,wqbuf_firstindex,wqbuf_lastindex;
1305f1c579b1SScott Long 			PUCHAR pQbuffer,ptmpuserbuffer=pccbioctlfld->ioctldatabuffer;
1306f1c579b1SScott Long 
1307f1c579b1SScott Long             s=splcam();
1308f1c579b1SScott Long             user_len=pccbioctl->Length;
1309f1c579b1SScott Long 
1310f1c579b1SScott Long  			/*check if data xfer length of this request will overflow my array qbuffer */
1311f1c579b1SScott Long 			wqbuf_lastindex=pACB->wqbuf_lastindex;
1312f1c579b1SScott Long 			wqbuf_firstindex=pACB->wqbuf_firstindex;
1313f1c579b1SScott Long 			my_empty_len=(wqbuf_firstindex-wqbuf_lastindex-1)&(ARCMSR_MAX_QBUFFER-1);
1314f1c579b1SScott Long 			if(my_empty_len>=user_len)
1315f1c579b1SScott Long 			{
1316f1c579b1SScott Long 				while(user_len>0)
1317f1c579b1SScott Long 				{
1318f1c579b1SScott Long 					/*copy srb data to wqbuffer*/
1319f1c579b1SScott Long 					pQbuffer=&pACB->wqbuffer[pACB->wqbuf_lastindex];
1320f1c579b1SScott Long 					memcpy(pQbuffer,ptmpuserbuffer,1);
1321f1c579b1SScott Long 					pACB->wqbuf_lastindex++;
1322f1c579b1SScott Long 					pACB->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER;/*if last index number set it to 0 */
1323f1c579b1SScott Long  					ptmpuserbuffer++;
1324f1c579b1SScott Long 					user_len--;
1325f1c579b1SScott Long 				}
1326f1c579b1SScott Long 				/*post fist Qbuffer*/
1327f1c579b1SScott Long 				if(pACB->acb_flags & ACB_F_IOCTL_WQBUFFER_CLEARED)
1328f1c579b1SScott Long 				{
1329f1c579b1SScott Long 					pACB->acb_flags &=~ACB_F_IOCTL_WQBUFFER_CLEARED;
1330f1c579b1SScott Long  					arcmsr_post_Qbuffer(pACB);
1331f1c579b1SScott Long 				}
1332f1c579b1SScott Long 				pccbioctl->ReturnCode=ARCMSR_IOCTL_RETURNCODE_OK;
1333f1c579b1SScott Long 			}
1334f1c579b1SScott Long 			else
1335f1c579b1SScott Long 			{
1336f1c579b1SScott Long 				pccbioctl->ReturnCode=ARCMSR_IOCTL_RETURNCODE_ERROR;
1337f1c579b1SScott Long 			}
1338f1c579b1SScott Long 			splx(s);
1339f1c579b1SScott Long 			return ARC_IOCTL_SUCCESS;
1340f1c579b1SScott Long 		}
1341f1c579b1SScott Long 		break;
1342f1c579b1SScott Long 	case ARCMSR_IOCTL_CLEAR_RQBUFFER:
1343f1c579b1SScott Long 		{
1344f1c579b1SScott Long 			ULONG s;
1345f1c579b1SScott Long 			PUCHAR pQbuffer=pACB->rqbuffer;
1346f1c579b1SScott Long             s=splcam();
1347f1c579b1SScott Long 			if(pACB->acb_flags & ACB_F_IOPDATA_OVERFLOW)
1348f1c579b1SScott Long 			{
1349f1c579b1SScott Long                 pACB->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
1350f1c579b1SScott Long                 CHIP_REG_WRITE32(&pACB->pmu->inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK);/*signature, let IOP331 know data has been readed */
1351f1c579b1SScott Long 			}
1352f1c579b1SScott Long             pACB->acb_flags |= ACB_F_IOCTL_RQBUFFER_CLEARED;
1353f1c579b1SScott Long 			pACB->rqbuf_firstindex=0;
1354f1c579b1SScott Long 			pACB->rqbuf_lastindex=0;
1355f1c579b1SScott Long             memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER);
1356f1c579b1SScott Long 			pccbioctl->ReturnCode=ARCMSR_IOCTL_RETURNCODE_OK;
1357f1c579b1SScott Long 			splx(s);
1358f1c579b1SScott Long 			return ARC_IOCTL_SUCCESS;
1359f1c579b1SScott Long 		}
1360f1c579b1SScott Long 		break;
1361f1c579b1SScott Long 	case ARCMSR_IOCTL_CLEAR_WQBUFFER:
1362f1c579b1SScott Long 		{
1363f1c579b1SScott Long 			ULONG s;
1364f1c579b1SScott Long 			PUCHAR pQbuffer=pACB->wqbuffer;
1365f1c579b1SScott Long 
1366f1c579b1SScott Long             s=splcam();
1367f1c579b1SScott Long 			if(pACB->acb_flags & ACB_F_IOPDATA_OVERFLOW)
1368f1c579b1SScott Long 			{
1369f1c579b1SScott Long                 pACB->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
1370f1c579b1SScott Long                 CHIP_REG_WRITE32(&pACB->pmu->inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK);/*signature, let IOP331 know data has been readed */
1371f1c579b1SScott Long 			}
1372f1c579b1SScott Long 			pACB->acb_flags |= ACB_F_IOCTL_WQBUFFER_CLEARED;
1373f1c579b1SScott Long 			pACB->wqbuf_firstindex=0;
1374f1c579b1SScott Long 			pACB->wqbuf_lastindex=0;
1375f1c579b1SScott Long             memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER);
1376f1c579b1SScott Long 			pccbioctl->ReturnCode=ARCMSR_IOCTL_RETURNCODE_OK;
1377f1c579b1SScott Long 			splx(s);
1378f1c579b1SScott Long 			return ARC_IOCTL_SUCCESS;
1379f1c579b1SScott Long 		}
1380f1c579b1SScott Long 		break;
1381f1c579b1SScott Long 	case ARCMSR_IOCTL_CLEAR_ALLQBUFFER:
1382f1c579b1SScott Long 		{
1383f1c579b1SScott Long 			ULONG s;
1384f1c579b1SScott Long 			PUCHAR pQbuffer;
1385f1c579b1SScott Long 
1386f1c579b1SScott Long             s=splcam();
1387f1c579b1SScott Long 			if(pACB->acb_flags & ACB_F_IOPDATA_OVERFLOW)
1388f1c579b1SScott Long 			{
1389f1c579b1SScott Long                 pACB->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
1390f1c579b1SScott Long                 CHIP_REG_WRITE32(&pACB->pmu->inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK);/*signature, let IOP331 know data has been readed */
1391f1c579b1SScott Long 			}
1392f1c579b1SScott Long 			pACB->acb_flags |= (ACB_F_IOCTL_WQBUFFER_CLEARED|ACB_F_IOCTL_RQBUFFER_CLEARED);
1393f1c579b1SScott Long 			pACB->rqbuf_firstindex=0;
1394f1c579b1SScott Long 			pACB->rqbuf_lastindex=0;
1395f1c579b1SScott Long 			pACB->wqbuf_firstindex=0;
1396f1c579b1SScott Long 			pACB->wqbuf_lastindex=0;
1397f1c579b1SScott Long 			pQbuffer=pACB->rqbuffer;
1398f1c579b1SScott Long             memset(pQbuffer, 0, sizeof(struct _QBUFFER));
1399f1c579b1SScott Long 			pQbuffer=pACB->wqbuffer;
1400f1c579b1SScott Long             memset(pQbuffer, 0, sizeof(struct _QBUFFER));
1401f1c579b1SScott Long 			pccbioctl->ReturnCode=ARCMSR_IOCTL_RETURNCODE_OK;
1402f1c579b1SScott Long 			splx(s);
1403f1c579b1SScott Long 			return ARC_IOCTL_SUCCESS;
1404f1c579b1SScott Long 		}
1405f1c579b1SScott Long 		break;
1406f1c579b1SScott Long 	case ARCMSR_IOCTL_RETURN_CODE_3F:
1407f1c579b1SScott Long 		{
1408f1c579b1SScott Long 			pccbioctl->ReturnCode=ARCMSR_IOCTL_RETURNCODE_3F;
1409f1c579b1SScott Long 			return ARC_IOCTL_SUCCESS;
1410f1c579b1SScott Long 		}
1411f1c579b1SScott Long 		break;
1412f1c579b1SScott Long 	case ARCMSR_IOCTL_SAY_HELLO:
1413f1c579b1SScott Long 		{
1414f1c579b1SScott Long 			PCMD_IOCTL_FIELD pccbioctlfld=(PCMD_IOCTL_FIELD)arg;
1415f1c579b1SScott Long 			PCHAR hello_string="Hello! I am ARCMSR";
1416f1c579b1SScott Long 			PCHAR puserbuffer=(PUCHAR)pccbioctlfld->ioctldatabuffer;
1417f1c579b1SScott Long 
1418f1c579b1SScott Long 			if(memcpy(puserbuffer,hello_string,(SHORT)strlen(hello_string)))
1419f1c579b1SScott Long 			{
1420f1c579b1SScott Long 				pccbioctl->ReturnCode=ARCMSR_IOCTL_RETURNCODE_ERROR;
1421f1c579b1SScott Long                 return ENOIOCTL;
1422f1c579b1SScott Long 			}
1423f1c579b1SScott Long             pccbioctl->ReturnCode=ARCMSR_IOCTL_RETURNCODE_OK;
1424f1c579b1SScott Long 		    return ARC_IOCTL_SUCCESS;
1425f1c579b1SScott Long 		}
1426f1c579b1SScott Long 		break;
1427f1c579b1SScott Long 	}
1428f1c579b1SScott Long     return EINVAL;
1429f1c579b1SScott Long }
1430f1c579b1SScott Long /*
1431f1c579b1SScott Long **************************************************************************
1432f1c579b1SScott Long **
1433f1c579b1SScott Long **************************************************************************
1434f1c579b1SScott Long */
1435f1c579b1SScott Long PSRB arcmsr_get_freesrb(PACB pACB)
1436f1c579b1SScott Long {
1437f1c579b1SScott Long     PSRB pSRB=NULL;
1438f1c579b1SScott Long   	ULONG s;
1439f1c579b1SScott Long 	LONG srb_startindex,srb_doneindex;
1440f1c579b1SScott Long 
1441f1c579b1SScott Long     #if ARCMSR_DEBUG0
1442f1c579b1SScott Long 	printf("arcmsr_get_freesrb: srb_startindex=%d srb_doneindex=%d\n",pACB->srb_startindex,pACB->srb_doneindex);
1443f1c579b1SScott Long     #endif
1444f1c579b1SScott Long 
1445f1c579b1SScott Long 	s=splcam();
1446f1c579b1SScott Long 	srb_doneindex=pACB->srb_doneindex;
1447f1c579b1SScott Long 	srb_startindex=pACB->srb_startindex;
1448f1c579b1SScott Long 	pSRB=pACB->psrbringQ[srb_startindex];
1449f1c579b1SScott Long 	srb_startindex++;
1450f1c579b1SScott Long 	srb_startindex %= ARCMSR_MAX_FREESRB_NUM;
1451f1c579b1SScott Long 	if(srb_doneindex!=srb_startindex)
1452f1c579b1SScott Long 	{
1453f1c579b1SScott Long   		pACB->srb_startindex=srb_startindex;
1454f1c579b1SScott Long   	}
1455f1c579b1SScott Long 	else
1456f1c579b1SScott Long 	{
1457f1c579b1SScott Long         pSRB=NULL;
1458f1c579b1SScott Long 	}
1459f1c579b1SScott Long 	splx(s);
1460f1c579b1SScott Long 	return(pSRB);
1461f1c579b1SScott Long }
1462f1c579b1SScott Long /*
1463f1c579b1SScott Long *********************************************************************
1464f1c579b1SScott Long **
1465f1c579b1SScott Long **
1466f1c579b1SScott Long **
1467f1c579b1SScott Long *********************************************************************
1468f1c579b1SScott Long */
1469f1c579b1SScott Long static VOID arcmsr_executesrb(VOID *arg,bus_dma_segment_t *dm_segs,LONG nseg,LONG error)
1470f1c579b1SScott Long {
1471f1c579b1SScott Long 	PSRB	  pSRB=(PSRB)arg;
1472f1c579b1SScott Long     PACB      pACB;
1473f1c579b1SScott Long 	union ccb *pccb;
1474f1c579b1SScott Long 
1475f1c579b1SScott Long     #if ARCMSR_DEBUG0
1476f1c579b1SScott Long     printf("arcmsr_executesrb........................................ \n" );
1477f1c579b1SScott Long     #endif
1478f1c579b1SScott Long 
1479f1c579b1SScott Long 	pccb=pSRB->pccb;
1480f1c579b1SScott Long    	pACB=(PACB)pSRB->pACB;
1481f1c579b1SScott Long 	if(error != 0)
1482f1c579b1SScott Long 	{
1483f1c579b1SScott Long 		if(error != EFBIG)
1484f1c579b1SScott Long 		{
1485f1c579b1SScott Long 			printf("arcmsr_executesrb:%d Unexepected error %x returned from "  "bus_dmamap_load\n",pACB->pci_unit,error);
1486f1c579b1SScott Long 		}
1487f1c579b1SScott Long 		if(pccb->ccb_h.status == CAM_REQ_INPROG)
1488f1c579b1SScott Long 		{
1489f1c579b1SScott Long 			xpt_freeze_devq(pccb->ccb_h.path,/*count*/1);
1490f1c579b1SScott Long 			pccb->ccb_h.status=CAM_REQ_TOO_BIG|CAM_DEV_QFRZN;
1491f1c579b1SScott Long 		}
1492f1c579b1SScott Long 		xpt_done(pccb);
1493f1c579b1SScott Long 		return;
1494f1c579b1SScott Long 	}
1495f1c579b1SScott Long     arcmsr_build_srb(pSRB,dm_segs,nseg);
1496f1c579b1SScott Long 	if(pccb->ccb_h.status != CAM_REQ_INPROG)
1497f1c579b1SScott Long 	{
1498f1c579b1SScott Long 		if(nseg != 0)
1499f1c579b1SScott Long 		{
1500f1c579b1SScott Long 			bus_dmamap_unload(pACB->buffer_dmat,pSRB->dmamap);
1501f1c579b1SScott Long 		}
1502f1c579b1SScott Long 		xpt_done(pccb);
1503f1c579b1SScott Long 		return;
1504f1c579b1SScott Long 	}
1505f1c579b1SScott Long 	pccb->ccb_h.status |= CAM_SIM_QUEUED;
1506f1c579b1SScott Long 	if(pACB->srboutstandingcount < ARCMSR_MAX_OUTSTANDING_CMD)
1507f1c579b1SScott Long 	{
1508f1c579b1SScott Long 		/*
1509f1c579b1SScott Long 		******************************************************************
1510f1c579b1SScott Long 		** and we can make sure there were no pending srb in this duration
1511f1c579b1SScott Long 		******************************************************************
1512f1c579b1SScott Long 		*/
1513f1c579b1SScott Long     	arcmsr_post_srb(pACB,pSRB);
1514f1c579b1SScott Long 	}
1515f1c579b1SScott Long 	else
1516f1c579b1SScott Long 	{
1517f1c579b1SScott Long 		/*
1518f1c579b1SScott Long 		******************************************************************
1519f1c579b1SScott Long 		** Q of srbwaitexec will be post out when any outstanding command complete
1520f1c579b1SScott Long 		******************************************************************
1521f1c579b1SScott Long 		*/
1522f1c579b1SScott Long 		arcmsr_queue_wait2go_srb(pACB,pSRB);
1523f1c579b1SScott Long 	}
1524f1c579b1SScott Long 	return;
1525f1c579b1SScott Long }
1526f1c579b1SScott Long /*
1527f1c579b1SScott Long *****************************************************************************************
1528f1c579b1SScott Long **
1529f1c579b1SScott Long *****************************************************************************************
1530f1c579b1SScott Long */
1531f1c579b1SScott Long BOOLEAN arcmsr_seek_cmd2abort(union ccb * pabortccb)
1532f1c579b1SScott Long {
1533f1c579b1SScott Long  	PSRB pSRB,pfreesrb;
1534f1c579b1SScott Long     PACB pACB=(PACB) pabortccb->ccb_h.arcmsr_ccbacb_ptr;
1535f1c579b1SScott Long 	ULONG s,intmask_org,mask;
1536f1c579b1SScott Long     LONG i=0;
1537f1c579b1SScott Long 
1538f1c579b1SScott Long     #if ARCMSR_DEBUG0
1539f1c579b1SScott Long     printf("arcmsr_seek_cmd2abort.................. \n");
1540f1c579b1SScott Long     #endif
1541f1c579b1SScott Long 
1542f1c579b1SScott Long 	s=splcam();
1543f1c579b1SScott Long 	/*
1544f1c579b1SScott Long 	** It is the upper layer do abort command this lock just prior to calling us.
1545f1c579b1SScott Long 	** First determine if we currently own this command.
1546f1c579b1SScott Long 	** Start by searching the device queue. If not found
1547f1c579b1SScott Long 	** at all,and the system wanted us to just abort the
1548f1c579b1SScott Long 	** command return success.
1549f1c579b1SScott Long 	*/
1550f1c579b1SScott Long 	if(pACB->srboutstandingcount!=0)
1551f1c579b1SScott Long 	{
1552f1c579b1SScott Long 		/* Q back all outstanding srb into wait exec psrb Q*/
1553f1c579b1SScott Long 		pfreesrb=pACB->pfreesrb;
1554f1c579b1SScott Long 		for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++)
1555f1c579b1SScott Long 		{
1556f1c579b1SScott Long 	    	pSRB=&pfreesrb[i];
1557f1c579b1SScott Long 			if(pSRB->startdone==ARCMSR_SRB_START)
1558f1c579b1SScott Long 			{
1559f1c579b1SScott Long 				if(pSRB->pccb==pabortccb)
1560f1c579b1SScott Long 				{
1561f1c579b1SScott Long 					/* disable all outbound interrupt */
1562f1c579b1SScott Long 					intmask_org=CHIP_REG_READ32(&pACB->pmu->outbound_intmask);
1563f1c579b1SScott Long 					CHIP_REG_WRITE32(&pACB->pmu->outbound_intmask,intmask_org|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE);
1564f1c579b1SScott Long 				    /* talk to iop 331 outstanding command aborted*/
1565f1c579b1SScott Long 					arcmsr_abort_allcmd(pACB);
1566f1c579b1SScott Long 					if(arcmsr_wait_msgint_ready(pACB)!=TRUE)
1567f1c579b1SScott Long 					{
1568f1c579b1SScott Long 						printf("arcmsr_seek_cmd2abort: wait 'abort all outstanding command' timeout.................in \n");
1569f1c579b1SScott Long 					}
1570f1c579b1SScott Long 					/*clear all outbound posted Q*/
1571f1c579b1SScott Long 					for(i=0;i<ARCMSR_MAX_OUTSTANDING_CMD;i++)
1572f1c579b1SScott Long 					{
1573f1c579b1SScott Long 						CHIP_REG_READ32(&pACB->pmu->outbound_queueport);
1574f1c579b1SScott Long 					}
1575f1c579b1SScott Long 					pfreesrb=pACB->pfreesrb;
1576f1c579b1SScott Long 					for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++)
1577f1c579b1SScott Long 					{
1578f1c579b1SScott Long 	    				pSRB=&pfreesrb[i];
1579f1c579b1SScott Long 						if(pSRB->startdone==ARCMSR_SRB_START)
1580f1c579b1SScott Long 						{
1581f1c579b1SScott Long 							pSRB->startdone=ARCMSR_SRB_ABORTED;
1582f1c579b1SScott Long 							pSRB->pccb->ccb_h.status=CAM_REQ_ABORTED;
1583f1c579b1SScott Long 							arcmsr_srb_complete(pSRB);
1584f1c579b1SScott Long 						}
1585f1c579b1SScott Long 					}
1586f1c579b1SScott Long     			    /* enable all outbound interrupt */
1587f1c579b1SScott Long 			        mask=~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE|ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE|ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE);
1588f1c579b1SScott Long                     CHIP_REG_WRITE32(&pACB->pmu->outbound_intmask,intmask_org & mask);
1589f1c579b1SScott Long 					splx(s);
1590f1c579b1SScott Long 					return(TRUE);
1591f1c579b1SScott Long 				}
1592f1c579b1SScott Long 			}
1593f1c579b1SScott Long 		}
1594f1c579b1SScott Long 	}
1595f1c579b1SScott Long 	/*
1596f1c579b1SScott Long 	** seek this command at our command list
1597f1c579b1SScott Long 	** if command found then remove,abort it and free this SRB
1598f1c579b1SScott Long 	*/
1599f1c579b1SScott Long 	if(pACB->srbwait2gocount!=0)
1600f1c579b1SScott Long 	{
1601f1c579b1SScott Long 		for(i=0;i<ARCMSR_MAX_OUTSTANDING_CMD;i++)
1602f1c579b1SScott Long 		{
1603f1c579b1SScott Long 			pSRB=pACB->psrbwait2go[i];
1604f1c579b1SScott Long 			if(pSRB!=NULL)
1605f1c579b1SScott Long 			{
1606f1c579b1SScott Long 				if(pSRB->pccb==pabortccb)
1607f1c579b1SScott Long 				{
1608f1c579b1SScott Long 					pACB->psrbwait2go[i]=NULL;
1609f1c579b1SScott Long 					pSRB->startdone=ARCMSR_SRB_ABORTED;
1610f1c579b1SScott Long 					pSRB->pccb->ccb_h.status=CAM_REQ_ABORTED;
1611f1c579b1SScott Long 					arcmsr_srb_complete(pSRB);
1612f1c579b1SScott Long 	    			atomic_subtract_int(&pACB->srbwait2gocount,1);
1613f1c579b1SScott Long                     splx(s);
1614f1c579b1SScott Long 					return(TRUE);
1615f1c579b1SScott Long 				}
1616f1c579b1SScott Long 			}
1617f1c579b1SScott Long 		}
1618f1c579b1SScott Long 	}
1619f1c579b1SScott Long  	splx(s);
1620f1c579b1SScott Long 	return (FALSE);
1621f1c579b1SScott Long }
1622f1c579b1SScott Long /*
1623f1c579b1SScott Long ****************************************************************************
1624f1c579b1SScott Long **
1625f1c579b1SScott Long ****************************************************************************
1626f1c579b1SScott Long */
1627f1c579b1SScott Long VOID arcmsr_bus_reset(PACB pACB)
1628f1c579b1SScott Long {
1629f1c579b1SScott Long 	#if ARCMSR_DEBUG0
1630f1c579b1SScott Long 	printf("arcmsr_bus_reset.......................... \n");
1631f1c579b1SScott Long 	#endif
1632f1c579b1SScott Long 
1633f1c579b1SScott Long 	arcmsr_iop_reset(pACB);
1634f1c579b1SScott Long  	return;
1635f1c579b1SScott Long }
1636f1c579b1SScott Long /*
1637f1c579b1SScott Long *********************************************************************
1638f1c579b1SScott Long **
1639f1c579b1SScott Long **   CAM  Status field values
1640f1c579b1SScott Long **typedef enum {
1641f1c579b1SScott Long **	CAM_REQ_INPROG,		   CCB request is in progress
1642f1c579b1SScott Long **	CAM_REQ_CMP,		   CCB request completed without error
1643f1c579b1SScott Long **	CAM_REQ_ABORTED,	   CCB request aborted by the host
1644f1c579b1SScott Long **	CAM_UA_ABORT,		   Unable to abort CCB request
1645f1c579b1SScott Long **	CAM_REQ_CMP_ERR,	   CCB request completed with an error
1646f1c579b1SScott Long **	CAM_BUSY,		       CAM subsytem is busy
1647f1c579b1SScott Long **	CAM_REQ_INVALID,	   CCB request was invalid
1648f1c579b1SScott Long **	CAM_PATH_INVALID,	   Supplied Path ID is invalid
1649f1c579b1SScott Long **	CAM_DEV_NOT_THERE,	   SCSI Device Not Installed/there
1650f1c579b1SScott Long **	CAM_UA_TERMIO,		   Unable to terminate I/O CCB request
1651f1c579b1SScott Long **	CAM_SEL_TIMEOUT,	   Target Selection Timeout
1652f1c579b1SScott Long **	CAM_CMD_TIMEOUT,	   Command timeout
1653f1c579b1SScott Long **	CAM_SCSI_STATUS_ERROR,	   SCSI error, look at error code in CCB
1654f1c579b1SScott Long **	CAM_MSG_REJECT_REC,	   Message Reject Received
1655f1c579b1SScott Long **	CAM_SCSI_BUS_RESET,	   SCSI Bus Reset Sent/Received
1656f1c579b1SScott Long **	CAM_UNCOR_PARITY,	   Uncorrectable parity error occurred
1657f1c579b1SScott Long **	CAM_AUTOSENSE_FAIL=0x10,   Autosense: request sense cmd fail
1658f1c579b1SScott Long **	CAM_NO_HBA,		   No HBA Detected error
1659f1c579b1SScott Long **	CAM_DATA_RUN_ERR,	   Data Overrun error
1660f1c579b1SScott Long **	CAM_UNEXP_BUSFREE,	   Unexpected Bus Free
1661f1c579b1SScott Long **	CAM_SEQUENCE_FAIL,	   Target Bus Phase Sequence Failure
1662f1c579b1SScott Long **	CAM_CCB_LEN_ERR,	   CCB length supplied is inadequate
1663f1c579b1SScott Long **	CAM_PROVIDE_FAIL,	   Unable to provide requested capability
1664f1c579b1SScott Long **	CAM_BDR_SENT,		   A SCSI BDR msg was sent to target
1665f1c579b1SScott Long **	CAM_REQ_TERMIO,		   CCB request terminated by the host
1666f1c579b1SScott Long **	CAM_UNREC_HBA_ERROR,	   Unrecoverable Host Bus Adapter Error
1667f1c579b1SScott Long **	CAM_REQ_TOO_BIG,	   The request was too large for this host
1668f1c579b1SScott Long **	CAM_REQUEUE_REQ,
1669f1c579b1SScott Long **				 * This request should be requeued to preserve
1670f1c579b1SScott Long **				 * transaction ordering.  This typically occurs
1671f1c579b1SScott Long **				 * when the SIM recognizes an error that should
1672f1c579b1SScott Long **				 * freeze the queue and must place additional
1673f1c579b1SScott Long **				 * requests for the target at the sim level
1674f1c579b1SScott Long **				 * back into the XPT queue.
1675f1c579b1SScott Long **
1676f1c579b1SScott Long **	CAM_IDE=0x33,		   Initiator Detected Error
1677f1c579b1SScott Long **	CAM_RESRC_UNAVAIL,	   Resource Unavailable
1678f1c579b1SScott Long **	CAM_UNACKED_EVENT,	   Unacknowledged Event by Host
1679f1c579b1SScott Long **	CAM_MESSAGE_RECV,	   Message Received in Host Target Mode
1680f1c579b1SScott Long **	CAM_INVALID_CDB,	   Invalid CDB received in Host Target Mode
1681f1c579b1SScott Long **	CAM_LUN_INVALID,	   Lun supplied is invalid
1682f1c579b1SScott Long **	CAM_TID_INVALID,	   Target ID supplied is invalid
1683f1c579b1SScott Long **	CAM_FUNC_NOTAVAIL,	   The requested function is not available
1684f1c579b1SScott Long **	CAM_NO_NEXUS,		   Nexus is not established
1685f1c579b1SScott Long **	CAM_IID_INVALID,	   The initiator ID is invalid
1686f1c579b1SScott Long **	CAM_CDB_RECVD,		   The SCSI CDB has been received
1687f1c579b1SScott Long **	CAM_LUN_ALRDY_ENA,	   The LUN is already eanbeld for target mode
1688f1c579b1SScott Long **	CAM_SCSI_BUSY,		   SCSI Bus Busy
1689f1c579b1SScott Long **
1690f1c579b1SScott Long **	CAM_DEV_QFRZN=0x40,	   The DEV queue is frozen w/this err
1691f1c579b1SScott Long **
1692f1c579b1SScott Long **				   Autosense data valid for target
1693f1c579b1SScott Long **	CAM_AUTOSNS_VALID=0x80,
1694f1c579b1SScott Long **	CAM_RELEASE_SIMQ=0x100,   SIM ready to take more commands
1695f1c579b1SScott Long **	CAM_SIM_QUEUED  =0x200,   SIM has this command in it's queue
1696f1c579b1SScott Long **
1697f1c579b1SScott Long **	CAM_STATUS_MASK=0x3F,	   Mask bits for just the status #
1698f1c579b1SScott Long **
1699f1c579b1SScott Long **				   Target Specific Adjunct Status
1700f1c579b1SScott Long **	CAM_SENT_SENSE=0x40000000	   sent sense with status
1701f1c579b1SScott Long **} cam_status;
1702f1c579b1SScott Long **
1703f1c579b1SScott Long **union ccb {
1704f1c579b1SScott Long **			struct	ccb_hdr			ccb_h;	 For convenience
1705f1c579b1SScott Long **			struct	ccb_scsiio		csio;
1706f1c579b1SScott Long **			struct	ccb_getdev		cgd;
1707f1c579b1SScott Long **			struct	ccb_getdevlist		cgdl;
1708f1c579b1SScott Long **			struct	ccb_pathinq		cpi;
1709f1c579b1SScott Long **			struct	ccb_relsim		crs;
1710f1c579b1SScott Long **			struct	ccb_setasync		csa;
1711f1c579b1SScott Long **			struct	ccb_setdev		csd;
1712f1c579b1SScott Long **			struct	ccb_pathstats		cpis;
1713f1c579b1SScott Long **			struct	ccb_getdevstats		cgds;
1714f1c579b1SScott Long **			struct	ccb_dev_match		cdm;
1715f1c579b1SScott Long **			struct	ccb_trans_settings	cts;
1716f1c579b1SScott Long **			struct	ccb_calc_geometry	ccg;
1717f1c579b1SScott Long **			struct	ccb_abort		cab;
1718f1c579b1SScott Long **			struct	ccb_resetbus		crb;
1719f1c579b1SScott Long **			struct	ccb_resetdev		crd;
1720f1c579b1SScott Long **			struct	ccb_termio		tio;
1721f1c579b1SScott Long **			struct	ccb_accept_tio		atio;
1722f1c579b1SScott Long **			struct	ccb_scsiio		ctio;
1723f1c579b1SScott Long **			struct	ccb_en_lun		cel;
1724f1c579b1SScott Long **			struct	ccb_immed_notify	cin;
1725f1c579b1SScott Long **			struct	ccb_notify_ack		cna;
1726f1c579b1SScott Long **			struct	ccb_eng_inq		cei;
1727f1c579b1SScott Long **			struct	ccb_eng_exec		cee;
1728f1c579b1SScott Long **			struct 	ccb_rescan		crcn;
1729f1c579b1SScott Long **			struct  ccb_debug		cdbg;
1730f1c579b1SScott Long **          }
1731f1c579b1SScott Long **
1732f1c579b1SScott Long **struct ccb_hdr {
1733f1c579b1SScott Long **	cam_pinfo	    pinfo;	                                    "" Info for priority scheduling
1734f1c579b1SScott Long **	camq_entry	    xpt_links;	                                "" For chaining in the XPT layer
1735f1c579b1SScott Long **	camq_entry	    sim_links;	                                "" For chaining in the SIM layer
1736f1c579b1SScott Long **	camq_entry	    periph_links;                               "" For chaining in the type driver
1737f1c579b1SScott Long **	u_int32_t	    retry_count;
1738f1c579b1SScott Long **	void		    (*cbfcnp)(struct cam_periph *, union ccb *);"" Callback on completion function
1739f1c579b1SScott Long **	xpt_opcode	    func_code;	                                "" XPT function code
1740f1c579b1SScott Long **	u_int32_t	    status;	                                    "" Status returned by CAM subsystem
1741f1c579b1SScott Long **	struct		    cam_path *path;                             "" Compiled path for this ccb
1742f1c579b1SScott Long **	path_id_t	    path_id;	                                "" Path ID for the request
1743f1c579b1SScott Long **	target_id_t	    target_id;	                                "" Target device ID
1744f1c579b1SScott Long **	lun_id_t	    target_lun;                              	"" Target LUN number
1745f1c579b1SScott Long **	u_int32_t	    flags;
1746f1c579b1SScott Long **	ccb_ppriv_area	periph_priv;
1747f1c579b1SScott Long **	ccb_spriv_area	sim_priv;
1748f1c579b1SScott Long **	u_int32_t	    timeout;	                                "" Timeout value
1749f1c579b1SScott Long **	struct		    callout_handle timeout_ch;                  "" Callout handle used for timeouts
1750f1c579b1SScott Long **};
1751f1c579b1SScott Long **
1752f1c579b1SScott Long **typedef union {
1753f1c579b1SScott Long **	u_int8_t  *cdb_ptr;		               "" Pointer to the CDB bytes to send
1754f1c579b1SScott Long **	u_int8_t  cdb_bytes[IOCDBLEN];         "" Area for the CDB send
1755f1c579b1SScott Long **} cdb_t;
1756f1c579b1SScott Long **
1757f1c579b1SScott Long ** SCSI I/O Request CCB used for the XPT_SCSI_IO and XPT_CONT_TARGET_IO
1758f1c579b1SScott Long ** function codes.
1759f1c579b1SScott Long **
1760f1c579b1SScott Long **struct ccb_scsiio {
1761f1c579b1SScott Long **	struct	   ccb_hdr ccb_h;
1762f1c579b1SScott Long **	union	   ccb *next_ccb;	           "" Ptr for next CCB for action
1763f1c579b1SScott Long **	u_int8_t   *req_map;		           "" Ptr to mapping info
1764f1c579b1SScott Long **	u_int8_t   *data_ptr;		           "" Ptr to the data buf/SG list
1765f1c579b1SScott Long **	u_int32_t  dxfer_len;		           "" Data transfer length
1766f1c579b1SScott Long **	struct     scsi_sense_data sense_data; "" Autosense storage
1767f1c579b1SScott Long **	u_int8_t   sense_len;		           "" Number of bytes to autosense
1768f1c579b1SScott Long **	u_int8_t   cdb_len;		               "" Number of bytes for the CDB
1769f1c579b1SScott Long **	u_int16_t  sglist_cnt;		           "" Number of SG list entries
1770f1c579b1SScott Long **	u_int8_t   scsi_status;		           "" Returned SCSI status
1771f1c579b1SScott Long **	u_int8_t   sense_resid;		           "" Autosense resid length: 2's comp
1772f1c579b1SScott Long **	u_int32_t  resid;		               "" Transfer residual length: 2's comp
1773f1c579b1SScott Long **	cdb_t	   cdb_io;		               "" Union for CDB bytes/pointer
1774f1c579b1SScott Long **	u_int8_t   *msg_ptr;		           "" Pointer to the message buffer
1775f1c579b1SScott Long **	u_int16_t  msg_len;		               "" Number of bytes for the Message
1776f1c579b1SScott Long **	u_int8_t   tag_action;		           "" What to do for tag queueing
1777f1c579b1SScott Long **#define	CAM_TAG_ACTION_NONE	0x00       "" The tag action should be either the define below (to send a non-tagged transaction) or one of the defined scsi tag messages from scsi_message.h.
1778f1c579b1SScott Long **	u_int	   tag_id;		               "" tag id from initator (target mode)
1779f1c579b1SScott Long **	u_int	   init_id;		               "" initiator id of who selected
1780f1c579b1SScott Long **}
1781f1c579b1SScott Long *********************************************************************
1782f1c579b1SScott Long */
1783f1c579b1SScott Long static VOID arcmsr_action(struct cam_sim * psim,union ccb * pccb)
1784f1c579b1SScott Long {
1785f1c579b1SScott Long 	PACB  pACB;
1786f1c579b1SScott Long 
1787f1c579b1SScott Long 	#if ARCMSR_DEBUG0
1788f1c579b1SScott Long     printf("arcmsr_action ..................................\n" );
1789f1c579b1SScott Long     #endif
1790f1c579b1SScott Long 
1791f1c579b1SScott Long 	pACB=(PACB) cam_sim_softc(psim);
1792f1c579b1SScott Long 	if(pACB==NULL)
1793f1c579b1SScott Long 	{
1794f1c579b1SScott Long     	pccb->ccb_h.status=CAM_REQ_INVALID;
1795f1c579b1SScott Long 		xpt_done(pccb);
1796f1c579b1SScott Long 		return;
1797f1c579b1SScott Long 	}
1798f1c579b1SScott Long 	switch (pccb->ccb_h.func_code)
1799f1c579b1SScott Long 	{
1800f1c579b1SScott Long 	case XPT_SCSI_IO:
1801f1c579b1SScott Long 		{
1802f1c579b1SScott Long 	    	PSRB pSRB;
1803f1c579b1SScott Long 			#if ARCMSR_DEBUG0
1804f1c579b1SScott Long 			printf("arcmsr_action: XPT_SCSI_IO......................\n" );
1805f1c579b1SScott Long 			#endif
1806f1c579b1SScott Long 
1807f1c579b1SScott Long 			if((pSRB=arcmsr_get_freesrb(pACB)) == NULL)
1808f1c579b1SScott Long 			{
1809f1c579b1SScott Long 				pccb->ccb_h.status=CAM_RESRC_UNAVAIL;
1810f1c579b1SScott Long 				xpt_done(pccb);
1811f1c579b1SScott Long 				return;
1812f1c579b1SScott Long 			}
1813f1c579b1SScott Long 			pccb->ccb_h.arcmsr_ccbsrb_ptr=pSRB;
1814f1c579b1SScott Long 			pccb->ccb_h.arcmsr_ccbacb_ptr=pACB;
1815f1c579b1SScott Long 			pSRB->pccb=pccb;
1816f1c579b1SScott Long 			if((pccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE)
1817f1c579b1SScott Long 			{
1818f1c579b1SScott Long 				if((pccb->ccb_h.flags & CAM_SCATTER_VALID) == 0)
1819f1c579b1SScott Long 				{
1820f1c579b1SScott Long 					if((pccb->ccb_h.flags & CAM_DATA_PHYS) == 0)
1821f1c579b1SScott Long 					{
1822f1c579b1SScott Long 						LONG error,s;
1823f1c579b1SScott Long 
1824f1c579b1SScott Long 						s=splsoftvm();
1825f1c579b1SScott Long 						error =	bus_dmamap_load(pACB->buffer_dmat,pSRB->dmamap,pccb->csio.data_ptr,pccb->csio.dxfer_len,arcmsr_executesrb,pSRB,/*flags*/0);
1826f1c579b1SScott Long 	         			if(error == EINPROGRESS)
1827f1c579b1SScott Long 						{
1828f1c579b1SScott Long 							xpt_freeze_simq(pACB->psim,1);
1829f1c579b1SScott Long 							pccb->ccb_h.status |= CAM_RELEASE_SIMQ;
1830f1c579b1SScott Long 						}
1831f1c579b1SScott Long 						splx(s);
1832f1c579b1SScott Long 					}
1833f1c579b1SScott Long 					else
1834f1c579b1SScott Long 					{
1835f1c579b1SScott Long 						struct bus_dma_segment seg;
1836f1c579b1SScott Long 
1837f1c579b1SScott Long 						seg.ds_addr=(bus_addr_t)pccb->csio.data_ptr;
1838f1c579b1SScott Long 						seg.ds_len=pccb->csio.dxfer_len;
1839f1c579b1SScott Long 						arcmsr_executesrb(pSRB,&seg,1,0);
1840f1c579b1SScott Long 					}
1841f1c579b1SScott Long 				}
1842f1c579b1SScott Long 				else
1843f1c579b1SScott Long 				{
1844f1c579b1SScott Long 					struct bus_dma_segment *segs;
1845f1c579b1SScott Long 
1846f1c579b1SScott Long 					if((pccb->ccb_h.flags & CAM_SG_LIST_PHYS) == 0 || (pccb->ccb_h.flags & CAM_DATA_PHYS) != 0)
1847f1c579b1SScott Long 					{
1848f1c579b1SScott Long 						pccb->ccb_h.status=CAM_PROVIDE_FAIL;
1849f1c579b1SScott Long 						xpt_done(pccb);
1850f1c579b1SScott Long 						free(pSRB,M_DEVBUF);
1851f1c579b1SScott Long 						return;
1852f1c579b1SScott Long 					}
1853f1c579b1SScott Long 					segs=(struct bus_dma_segment *)pccb->csio.data_ptr;
1854f1c579b1SScott Long 					arcmsr_executesrb(pSRB,segs,pccb->csio.sglist_cnt,0);
1855f1c579b1SScott Long 				}
1856f1c579b1SScott Long 			}
1857f1c579b1SScott Long 			else
1858f1c579b1SScott Long 			{
1859f1c579b1SScott Long 				arcmsr_executesrb(pSRB,NULL,0,0);
1860f1c579b1SScott Long 			}
1861f1c579b1SScott Long 			break;
1862f1c579b1SScott Long 		}
1863f1c579b1SScott Long 	case XPT_TARGET_IO:
1864f1c579b1SScott Long 		{
1865f1c579b1SScott Long 			#if ARCMSR_DEBUG0
1866f1c579b1SScott Long 			printf("arcmsr_action: XPT_TARGET_IO\n" );
1867f1c579b1SScott Long 			#endif
1868f1c579b1SScott Long 			/*
1869f1c579b1SScott Long 			** target mode not yet support vendor specific commands.
1870f1c579b1SScott Long 			*/
1871f1c579b1SScott Long   			pccb->ccb_h.status=CAM_REQ_CMP;
1872f1c579b1SScott Long 			xpt_done(pccb);
1873f1c579b1SScott Long 			break;
1874f1c579b1SScott Long 		}
1875f1c579b1SScott Long 	case XPT_PATH_INQ:
1876f1c579b1SScott Long 		{
1877f1c579b1SScott Long 			struct ccb_pathinq *cpi=&pccb->cpi;
1878f1c579b1SScott Long 
1879f1c579b1SScott Long 			#if ARCMSR_DEBUG0
1880f1c579b1SScott Long 			printf("arcmsr_action: XPT_PATH_INQ\n" );
1881f1c579b1SScott Long 			#endif
1882f1c579b1SScott Long 			cpi->version_num=1;
1883f1c579b1SScott Long 			cpi->hba_inquiry=PI_SDTR_ABLE | PI_TAG_ABLE;
1884f1c579b1SScott Long 			cpi->target_sprt=0;
1885f1c579b1SScott Long 			cpi->hba_misc=0;
1886f1c579b1SScott Long 			cpi->hba_eng_cnt=0;
1887f1c579b1SScott Long 			cpi->max_target=ARCMSR_MAX_TARGETID;
1888f1c579b1SScott Long 			cpi->max_lun=ARCMSR_MAX_TARGETLUN;	/* 7 or 0 */
1889f1c579b1SScott Long 			cpi->initiator_id=ARCMSR_SCSI_INITIATOR_ID;
1890f1c579b1SScott Long 			cpi->bus_id=cam_sim_bus(psim);
1891f1c579b1SScott Long 			strncpy(cpi->sim_vid,"FreeBSD",SIM_IDLEN);
1892f1c579b1SScott Long 			strncpy(cpi->hba_vid,"ARCMSR",HBA_IDLEN);
1893f1c579b1SScott Long 			strncpy(cpi->dev_name,cam_sim_name(psim),DEV_IDLEN);
1894f1c579b1SScott Long 			cpi->unit_number=cam_sim_unit(psim);
1895f1c579b1SScott Long 			cpi->ccb_h.status=CAM_REQ_CMP;
1896f1c579b1SScott Long 			xpt_done(pccb);
1897f1c579b1SScott Long 			break;
1898f1c579b1SScott Long 		}
1899f1c579b1SScott Long 	case XPT_ABORT:
1900f1c579b1SScott Long 		{
1901f1c579b1SScott Long 			union ccb *pabort_ccb;
1902f1c579b1SScott Long 
1903f1c579b1SScott Long 			#if ARCMSR_DEBUG0
1904f1c579b1SScott Long 			printf("arcmsr_action: XPT_ABORT\n" );
1905f1c579b1SScott Long 			#endif
1906f1c579b1SScott Long 			pabort_ccb=pccb->cab.abort_ccb;
1907f1c579b1SScott Long 			switch (pabort_ccb->ccb_h.func_code)
1908f1c579b1SScott Long 			{
1909f1c579b1SScott Long 			case XPT_ACCEPT_TARGET_IO:
1910f1c579b1SScott Long 			case XPT_IMMED_NOTIFY:
1911f1c579b1SScott Long 			case XPT_CONT_TARGET_IO:
1912f1c579b1SScott Long 				if(arcmsr_seek_cmd2abort(pabort_ccb)==TRUE)
1913f1c579b1SScott Long 				{
1914f1c579b1SScott Long 					pabort_ccb->ccb_h.status=CAM_REQ_ABORTED;
1915f1c579b1SScott Long 					xpt_done(pabort_ccb);
1916f1c579b1SScott Long 					pccb->ccb_h.status=CAM_REQ_CMP;
1917f1c579b1SScott Long 				}
1918f1c579b1SScott Long 				else
1919f1c579b1SScott Long 				{
1920f1c579b1SScott Long 					xpt_print_path(pabort_ccb->ccb_h.path);
1921f1c579b1SScott Long 					printf("Not found\n");
1922f1c579b1SScott Long 					pccb->ccb_h.status=CAM_PATH_INVALID;
1923f1c579b1SScott Long 				}
1924f1c579b1SScott Long 				break;
1925f1c579b1SScott Long 			case XPT_SCSI_IO:
1926f1c579b1SScott Long 				pccb->ccb_h.status=CAM_UA_ABORT;
1927f1c579b1SScott Long 				break;
1928f1c579b1SScott Long 			default:
1929f1c579b1SScott Long 				pccb->ccb_h.status=CAM_REQ_INVALID;
1930f1c579b1SScott Long 				break;
1931f1c579b1SScott Long 			}
1932f1c579b1SScott Long 			xpt_done(pccb);
1933f1c579b1SScott Long 			break;
1934f1c579b1SScott Long 		}
1935f1c579b1SScott Long 	case XPT_RESET_BUS:
1936f1c579b1SScott Long 	case XPT_RESET_DEV:
1937f1c579b1SScott Long 		{
1938f1c579b1SScott Long 			LONG     i;
1939f1c579b1SScott Long 
1940f1c579b1SScott Long 			#if ARCMSR_DEBUG0
1941f1c579b1SScott Long 			printf("arcmsr_action: XPT_RESET_BUS\n" );
1942f1c579b1SScott Long 			#endif
1943f1c579b1SScott Long             arcmsr_bus_reset(pACB);
1944f1c579b1SScott Long 			for (i=0; i < 500; i++)
1945f1c579b1SScott Long 			{
1946f1c579b1SScott Long 				DELAY(1000);
1947f1c579b1SScott Long 			}
1948f1c579b1SScott Long 			pccb->ccb_h.status=CAM_REQ_CMP;
1949f1c579b1SScott Long 			xpt_done(pccb);
1950f1c579b1SScott Long 			break;
1951f1c579b1SScott Long 		}
1952f1c579b1SScott Long 	case XPT_TERM_IO:
1953f1c579b1SScott Long 		{
1954f1c579b1SScott Long 			#if ARCMSR_DEBUG0
1955f1c579b1SScott Long 			printf("arcmsr_action: XPT_TERM_IO\n" );
1956f1c579b1SScott Long 			#endif
1957f1c579b1SScott Long 			pccb->ccb_h.status=CAM_REQ_INVALID;
1958f1c579b1SScott Long 			xpt_done(pccb);
1959f1c579b1SScott Long 			break;
1960f1c579b1SScott Long 		}
1961f1c579b1SScott Long 	case XPT_GET_TRAN_SETTINGS:
1962f1c579b1SScott Long 		{
1963f1c579b1SScott Long 			struct ccb_trans_settings *cts;
1964f1c579b1SScott Long 			ULONG s;
1965f1c579b1SScott Long 
1966f1c579b1SScott Long 			#if ARCMSR_DEBUG0
1967f1c579b1SScott Long 			printf("arcmsr_action: XPT_GET_TRAN_SETTINGS\n" );
1968f1c579b1SScott Long 			#endif
1969f1c579b1SScott Long 
1970f1c579b1SScott Long 			cts=&pccb->cts;
1971f1c579b1SScott Long 			s=splcam();
1972f1c579b1SScott Long 			cts->flags=(CCB_TRANS_DISC_ENB | CCB_TRANS_TAG_ENB);
1973f1c579b1SScott Long 			cts->sync_period=3;
1974f1c579b1SScott Long 			cts->sync_offset=32;
1975f1c579b1SScott Long 			cts->bus_width=MSG_EXT_WDTR_BUS_16_BIT;
1976f1c579b1SScott Long             cts->valid=CCB_TRANS_SYNC_RATE_VALID | CCB_TRANS_SYNC_OFFSET_VALID | CCB_TRANS_BUS_WIDTH_VALID | CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID;
1977f1c579b1SScott Long 			splx(s);
1978f1c579b1SScott Long 			pccb->ccb_h.status=CAM_REQ_CMP;
1979f1c579b1SScott Long 			xpt_done(pccb);
1980f1c579b1SScott Long 			break;
1981f1c579b1SScott Long 		}
1982f1c579b1SScott Long 	case XPT_SET_TRAN_SETTINGS:
1983f1c579b1SScott Long 		{
1984f1c579b1SScott Long 			#if ARCMSR_DEBUG0
1985f1c579b1SScott Long 			printf("arcmsr_action: XPT_SET_TRAN_SETTINGS\n" );
1986f1c579b1SScott Long 			#endif
1987f1c579b1SScott Long 		    pccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
1988f1c579b1SScott Long 		    xpt_done(pccb);
1989f1c579b1SScott Long 			break;
1990f1c579b1SScott Long 		}
1991f1c579b1SScott Long 	case XPT_CALC_GEOMETRY:
1992f1c579b1SScott Long 		{
1993f1c579b1SScott Long 			struct ccb_calc_geometry *ccg;
1994f1c579b1SScott Long 			ULONG size_mb;
1995f1c579b1SScott Long 			ULONG secs_per_cylinder;
1996f1c579b1SScott Long 
1997f1c579b1SScott Long 			#if ARCMSR_DEBUG0
1998f1c579b1SScott Long 			printf("arcmsr_action: XPT_CALC_GEOMETRY\n" );
1999f1c579b1SScott Long 			#endif
2000f1c579b1SScott Long 			ccg=&pccb->ccg;
2001f1c579b1SScott Long 			size_mb=ccg->volume_size/((1024L * 1024L)/ccg->block_size);
2002f1c579b1SScott Long 			if(size_mb > 1024 )
2003f1c579b1SScott Long 			{
2004f1c579b1SScott Long 				ccg->heads=255;
2005f1c579b1SScott Long 				ccg->secs_per_track=63;
2006f1c579b1SScott Long 			}
2007f1c579b1SScott Long 			else
2008f1c579b1SScott Long 			{
2009f1c579b1SScott Long 				ccg->heads=64;
2010f1c579b1SScott Long 				ccg->secs_per_track=32;
2011f1c579b1SScott Long 			}
2012f1c579b1SScott Long 			secs_per_cylinder=ccg->heads * ccg->secs_per_track;
2013f1c579b1SScott Long 			ccg->cylinders=ccg->volume_size / secs_per_cylinder;
2014f1c579b1SScott Long 			pccb->ccb_h.status=CAM_REQ_CMP;
2015f1c579b1SScott Long 			xpt_done(pccb);
2016f1c579b1SScott Long 			break;
2017f1c579b1SScott Long 		}
2018f1c579b1SScott Long 	default:
2019f1c579b1SScott Long 		#if ARCMSR_DEBUG0
2020f1c579b1SScott Long 			printf("arcmsr_action: invalid XPT function CAM_REQ_INVALID\n" );
2021f1c579b1SScott Long 			#endif
2022f1c579b1SScott Long     	pccb->ccb_h.status=CAM_REQ_INVALID;
2023f1c579b1SScott Long 		xpt_done(pccb);
2024f1c579b1SScott Long 		break;
2025f1c579b1SScott Long 	}
2026f1c579b1SScott Long 	return;
2027f1c579b1SScott Long }
2028f1c579b1SScott Long /*
2029f1c579b1SScott Long **********************************************************************
2030f1c579b1SScott Long **
2031f1c579b1SScott Long **  start background rebulid
2032f1c579b1SScott Long **
2033f1c579b1SScott Long **********************************************************************
2034f1c579b1SScott Long */
2035f1c579b1SScott Long VOID arcmsr_start_adapter_bgrb(PACB pACB)
2036f1c579b1SScott Long {
2037f1c579b1SScott Long 	#if ARCMSR_DEBUG0
2038f1c579b1SScott Long 	printf("arcmsr_start_adapter_bgrb.................................. \n");
2039f1c579b1SScott Long 	#endif
2040f1c579b1SScott Long 	pACB->acb_flags |= ACB_F_MSG_START_BGRB;
2041f1c579b1SScott Long 	pACB->acb_flags &= ~ACB_F_MSG_STOP_BGRB;
2042f1c579b1SScott Long     CHIP_REG_WRITE32(&pACB->pmu->inbound_msgaddr0,ARCMSR_INBOUND_MESG0_START_BGRB);
2043f1c579b1SScott Long 	return;
2044f1c579b1SScott Long }
2045f1c579b1SScott Long /*
2046f1c579b1SScott Long **********************************************************************
2047f1c579b1SScott Long **
2048f1c579b1SScott Long **  start background rebulid
2049f1c579b1SScott Long **
2050f1c579b1SScott Long **********************************************************************
2051f1c579b1SScott Long */
2052f1c579b1SScott Long VOID arcmsr_iop_init(PACB pACB)
2053f1c579b1SScott Long {
2054f1c579b1SScott Long     ULONG intmask_org,mask,outbound_doorbell,firmware_state=0;
2055f1c579b1SScott Long 
2056f1c579b1SScott Long 	#if ARCMSR_DEBUG0
2057f1c579b1SScott Long 	printf("arcmsr_iop_init.................................. \n");
2058f1c579b1SScott Long 	#endif
2059f1c579b1SScott Long 	do
2060f1c579b1SScott Long 	{
2061f1c579b1SScott Long         firmware_state=CHIP_REG_READ32(&pACB->pmu->outbound_msgaddr1);
2062f1c579b1SScott Long 	}while((firmware_state & ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK)==0);
2063f1c579b1SScott Long     /* disable all outbound interrupt */
2064f1c579b1SScott Long     intmask_org=CHIP_REG_READ32(&pACB->pmu->outbound_intmask);
2065f1c579b1SScott Long     CHIP_REG_WRITE32(&pACB->pmu->outbound_intmask,intmask_org|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE);
2066f1c579b1SScott Long 	/*start background rebuild*/
2067f1c579b1SScott Long 	arcmsr_start_adapter_bgrb(pACB);
2068f1c579b1SScott Long 	if(arcmsr_wait_msgint_ready(pACB)!=TRUE)
2069f1c579b1SScott Long 	{
2070f1c579b1SScott Long 		printf("arcmsr_HwInitialize: wait 'start adapter background rebulid' timeout................. \n");
2071f1c579b1SScott Long 	}
2072f1c579b1SScott Long 	/* clear Qbuffer if door bell ringed */
2073f1c579b1SScott Long 	outbound_doorbell=CHIP_REG_READ32(&pACB->pmu->outbound_doorbell);
2074f1c579b1SScott Long 	if(outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_WRITE_OK)
2075f1c579b1SScott Long 	{
2076f1c579b1SScott Long 		CHIP_REG_WRITE32(&pACB->pmu->outbound_doorbell,outbound_doorbell);/*clear interrupt */
2077f1c579b1SScott Long         CHIP_REG_WRITE32(&pACB->pmu->inbound_doorbell,ARCMSR_INBOUND_DRIVER_DATA_READ_OK);
2078f1c579b1SScott Long 	}
2079f1c579b1SScott Long 	/* enable outbound Post Queue,outbound message0,outbell doorbell Interrupt */
2080f1c579b1SScott Long 	mask=~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE|ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE|ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE);
2081f1c579b1SScott Long     CHIP_REG_WRITE32(&pACB->pmu->outbound_intmask,intmask_org & mask);
2082f1c579b1SScott Long 	pACB->outbound_int_enable = ~(intmask_org & mask) & 0x000000ff;
2083f1c579b1SScott Long 	pACB->acb_flags |=ACB_F_IOP_INITED;
2084f1c579b1SScott Long 	return;
2085f1c579b1SScott Long }
2086f1c579b1SScott Long /*
2087f1c579b1SScott Long **********************************************************************
2088f1c579b1SScott Long **
2089f1c579b1SScott Long **  map freesrb
2090f1c579b1SScott Long **
2091f1c579b1SScott Long **********************************************************************
2092f1c579b1SScott Long */
2093f1c579b1SScott Long static void arcmsr_map_freesrb(void *arg, bus_dma_segment_t *segs, int nseg, int error)
2094f1c579b1SScott Long {
2095f1c579b1SScott Long 	PACB pACB=arg;
2096f1c579b1SScott Long 	PSRB psrb_tmp,pfreesrb;
2097f1c579b1SScott Long 	ULONG cdb_phyaddr;
2098f1c579b1SScott Long 	LONG i;
2099f1c579b1SScott Long 
2100f1c579b1SScott Long     pfreesrb=(PSRB)pACB->uncacheptr;
2101f1c579b1SScott Long 	cdb_phyaddr=segs->ds_addr; /* We suppose bus_addr_t high part always 0 here*/
2102f1c579b1SScott Long 	if(((CPT2INT)pACB->uncacheptr & 0x1F)!=0)
2103f1c579b1SScott Long 	{
2104f1c579b1SScott Long 		pfreesrb=pfreesrb+(0x20-((CPT2INT)pfreesrb & 0x1F));
2105f1c579b1SScott Long 		cdb_phyaddr=cdb_phyaddr+(0x20-((CPT2INT)cdb_phyaddr & 0x1F));
2106f1c579b1SScott Long 	}
2107f1c579b1SScott Long 	/*
2108f1c579b1SScott Long 	********************************************************************
2109f1c579b1SScott Long 	** here we need to tell iop 331 our freesrb.HighPart
2110f1c579b1SScott Long 	** if freesrb.HighPart is not zero
2111f1c579b1SScott Long 	********************************************************************
2112f1c579b1SScott Long 	*/
2113f1c579b1SScott Long 	for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++)
2114f1c579b1SScott Long 	{
2115f1c579b1SScott Long 		psrb_tmp=&pfreesrb[i];
2116f1c579b1SScott Long 		if(((CPT2INT)psrb_tmp & 0x1F)==0) /*srb address must 32 (0x20) boundary*/
2117f1c579b1SScott Long 		{
2118f1c579b1SScott Long             if(bus_dmamap_create(pACB->buffer_dmat, /*flags*/0, &psrb_tmp->dmamap)!=0)
2119f1c579b1SScott Long 			{
2120f1c579b1SScott Long 				pACB->acb_flags |= ACB_F_MAPFREESRB_FAILD;
2121f1c579b1SScott Long 			    printf(" arcmsr_map_freesrb: (pSRB->dmamap) bus_dmamap_create ..............error\n");
2122f1c579b1SScott Long 			    return;
2123f1c579b1SScott Long 			}
2124f1c579b1SScott Long 			psrb_tmp->cdb_shifted_phyaddr=cdb_phyaddr >> 5;
2125f1c579b1SScott Long             psrb_tmp->pACB=pACB;
2126f1c579b1SScott Long 			pACB->psrbringQ[i]=psrb_tmp;
2127f1c579b1SScott Long 			cdb_phyaddr=cdb_phyaddr+sizeof(struct _SRB);
2128f1c579b1SScott Long  		}
2129f1c579b1SScott Long 		else
2130f1c579b1SScott Long 		{
2131f1c579b1SScott Long 			pACB->acb_flags |= ACB_F_MAPFREESRB_FAILD;
2132f1c579b1SScott Long 			printf(" arcmsr_map_freesrb:pfreesrb=%p i=%d this srb cross 32 bytes boundary ignored ......psrb_tmp=%p \n",pfreesrb,i,psrb_tmp);
2133f1c579b1SScott Long 			return;
2134f1c579b1SScott Long 		}
2135f1c579b1SScott Long 	}
2136f1c579b1SScott Long  	pACB->pfreesrb=pfreesrb;
2137f1c579b1SScott Long 	pACB->vir2phy_offset=(CPT2INT)psrb_tmp-(cdb_phyaddr-sizeof(struct _SRB));
2138f1c579b1SScott Long     return;
2139f1c579b1SScott Long }
2140f1c579b1SScott Long /*
2141f1c579b1SScott Long ************************************************************************
2142f1c579b1SScott Long **
2143f1c579b1SScott Long **
2144f1c579b1SScott Long ************************************************************************
2145f1c579b1SScott Long */
2146f1c579b1SScott Long VOID arcmsr_free_resource(PACB pACB)
2147f1c579b1SScott Long {
2148f1c579b1SScott Long 	/* remove the control device */
2149f1c579b1SScott Long 	if (pACB->ioctl_dev != NULL)
2150f1c579b1SScott Long 	{
2151f1c579b1SScott Long 		destroy_dev(pACB->ioctl_dev);
2152f1c579b1SScott Long 	}
2153f1c579b1SScott Long     bus_dmamap_unload(pACB->srb_dmat, pACB->srb_dmamap);
2154f1c579b1SScott Long     bus_dmamap_destroy(pACB->srb_dmat, pACB->srb_dmamap);
2155f1c579b1SScott Long     bus_dma_tag_destroy(pACB->srb_dmat);
2156f1c579b1SScott Long 	bus_dma_tag_destroy(pACB->buffer_dmat);
2157f1c579b1SScott Long 	bus_dma_tag_destroy(pACB->parent_dmat);
2158f1c579b1SScott Long 	return;
2159f1c579b1SScott Long }
2160f1c579b1SScott Long /*
2161f1c579b1SScott Long ************************************************************************
2162f1c579b1SScott Long ** PCI config header registers for all devices
2163f1c579b1SScott Long **
2164f1c579b1SScott Long ** #define PCIR_COMMAND	        0x04
2165f1c579b1SScott Long ** #define PCIM_CMD_PORTEN		0x0001
2166f1c579b1SScott Long ** #define PCIM_CMD_MEMEN		0x0002
2167f1c579b1SScott Long ** #define PCIM_CMD_BUSMASTEREN	0x0004
2168f1c579b1SScott Long ** #define PCIM_CMD_MWRICEN	    0x0010
2169f1c579b1SScott Long ** #define PCIM_CMD_PERRESPEN	0x0040
2170f1c579b1SScott Long **
2171f1c579b1SScott Long ** Function      : arcmsr_initialize
2172f1c579b1SScott Long ** Purpose       : initialize the internal structures for a given SCSI host
2173f1c579b1SScott Long ** Inputs        : host - pointer to this host adapter's structure
2174f1c579b1SScott Long ** Preconditions : when this function is called,the chip_type
2175f1c579b1SScott Long **	               field of the pACB structure MUST have been set.
2176f1c579b1SScott Long **
2177f1c579b1SScott Long ** 10h Base Address register #0
2178f1c579b1SScott Long ** 14h Base Address register #1
2179f1c579b1SScott Long ** 18h Base Address register #2
2180f1c579b1SScott Long ** 1Ch Base Address register #3
2181f1c579b1SScott Long ** 20h Base Address register #4
2182f1c579b1SScott Long ** 24h Base Address register #5
2183f1c579b1SScott Long ************************************************************************
2184f1c579b1SScott Long */
2185f1c579b1SScott Long static LONG arcmsr_initialize(device_t dev)
2186f1c579b1SScott Long {
2187f1c579b1SScott Long 	PACB pACB=device_get_softc(dev);
2188f1c579b1SScott Long 	LONG rid=PCI_BASE_ADDR0;
2189f1c579b1SScott Long 	vm_offset_t	mem_base;
2190f1c579b1SScott Long 	USHORT pci_command;
2191f1c579b1SScott Long 
2192f1c579b1SScott Long 	#if ARCMSR_DEBUG0
2193f1c579b1SScott Long 	printf("arcmsr_initialize..............................\n");
2194f1c579b1SScott Long 	#endif
2195f1c579b1SScott Long #if __FreeBSD_version >= 502010
2196f1c579b1SScott Long 	if (bus_dma_tag_create( /*parent*/NULL,
2197f1c579b1SScott Long 		                    /*alignemnt*/1,
2198f1c579b1SScott Long 				   			/*boundary*/0,
2199f1c579b1SScott Long 			       			/*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
2200f1c579b1SScott Long 			       			/*highaddr*/BUS_SPACE_MAXADDR,
2201f1c579b1SScott Long 			       			/*filter*/NULL,
2202f1c579b1SScott Long 							/*filterarg*/NULL,
2203f1c579b1SScott Long 			       			/*maxsize*/BUS_SPACE_MAXSIZE_32BIT,
2204f1c579b1SScott Long 			       			/*nsegments*/BUS_SPACE_UNRESTRICTED,
2205f1c579b1SScott Long 			       			/*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
2206f1c579b1SScott Long 			       			/*flags*/0,
2207f1c579b1SScott Long 							/*lockfunc*/NULL,
2208f1c579b1SScott Long 							/*lockarg*/NULL,
2209f1c579b1SScott Long 							&pACB->parent_dmat) != 0)
2210f1c579b1SScott Long #else
2211f1c579b1SScott Long 	if (bus_dma_tag_create( /*parent*/NULL,
2212f1c579b1SScott Long 		                    /*alignemnt*/1,
2213f1c579b1SScott Long 				   			/*boundary*/0,
2214f1c579b1SScott Long 			       			/*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
2215f1c579b1SScott Long 			       			/*highaddr*/BUS_SPACE_MAXADDR,
2216f1c579b1SScott Long 			       			/*filter*/NULL,
2217f1c579b1SScott Long 							/*filterarg*/NULL,
2218f1c579b1SScott Long 			       			/*maxsize*/BUS_SPACE_MAXSIZE_32BIT,
2219f1c579b1SScott Long 			       			/*nsegments*/BUS_SPACE_UNRESTRICTED,
2220f1c579b1SScott Long 			       			/*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
2221f1c579b1SScott Long 			       			/*flags*/0,
2222f1c579b1SScott Long 							&pACB->parent_dmat) != 0)
2223f1c579b1SScott Long #endif
2224f1c579b1SScott Long 	{
2225f1c579b1SScott Long 		printf("arcmsr_initialize: bus_dma_tag_create .......................failure!\n");
2226f1c579b1SScott Long 		return ENOMEM;
2227f1c579b1SScott Long 	}
2228f1c579b1SScott Long     /* Create a single tag describing a region large enough to hold all of the s/g lists we will need. */
2229f1c579b1SScott Long #if __FreeBSD_version >= 502010
2230f1c579b1SScott Long 	if(bus_dma_tag_create( /*parent_dmat*/pACB->parent_dmat,
2231f1c579b1SScott Long 		                   /*alignment*/1,
2232f1c579b1SScott Long 			               /*boundary*/0,
2233f1c579b1SScott Long 			               /*lowaddr*/BUS_SPACE_MAXADDR,
2234f1c579b1SScott Long 			               /*highaddr*/BUS_SPACE_MAXADDR,
2235f1c579b1SScott Long 			               /*filter*/NULL,
2236f1c579b1SScott Long 						   /*filterarg*/NULL,
2237f1c579b1SScott Long 			               /*maxsize*/MAXBSIZE,
2238f1c579b1SScott Long 						   /*nsegments*/ARCMSR_MAX_SG_ENTRIES,
2239f1c579b1SScott Long 			               /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
2240f1c579b1SScott Long 			               /*flags*/BUS_DMA_ALLOCNOW,
2241f1c579b1SScott Long 						   /*lockfunc*/busdma_lock_mutex,
2242f1c579b1SScott Long 						   /*lockarg*/&Giant,
2243f1c579b1SScott Long 			               &pACB->buffer_dmat) != 0)
2244f1c579b1SScott Long #else
2245f1c579b1SScott Long 	if(bus_dma_tag_create( /*parent_dmat*/pACB->parent_dmat,
2246f1c579b1SScott Long 		                   /*alignment*/1,
2247f1c579b1SScott Long 			               /*boundary*/0,
2248f1c579b1SScott Long 			               /*lowaddr*/BUS_SPACE_MAXADDR,
2249f1c579b1SScott Long 			               /*highaddr*/BUS_SPACE_MAXADDR,
2250f1c579b1SScott Long 			               /*filter*/NULL,
2251f1c579b1SScott Long 						   /*filterarg*/NULL,
2252f1c579b1SScott Long 			               /*maxsize*/MAXBSIZE,
2253f1c579b1SScott Long 						   /*nsegments*/ARCMSR_MAX_SG_ENTRIES,
2254f1c579b1SScott Long 			               /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
2255f1c579b1SScott Long 			               /*flags*/BUS_DMA_ALLOCNOW,
2256f1c579b1SScott Long 			               &pACB->buffer_dmat) != 0)
2257f1c579b1SScott Long #endif
2258f1c579b1SScott Long 	{
2259f1c579b1SScott Long 		bus_dma_tag_destroy(pACB->parent_dmat);
2260f1c579b1SScott Long 		printf("arcmsr_initialize: bus_dma_tag_create ............................failure!\n");
2261f1c579b1SScott Long 		return ENOMEM;
2262f1c579b1SScott Long     }
2263f1c579b1SScott Long 	/* DMA tag for our srb structures.... Allocate the pfreesrb memory */
2264f1c579b1SScott Long #if __FreeBSD_version >= 502010
2265f1c579b1SScott Long 	if (bus_dma_tag_create( /*parent_dmat*/pACB->parent_dmat,
2266f1c579b1SScott Long 		                    /*alignment*/1,
2267f1c579b1SScott Long 		                    /*boundary*/0,
2268f1c579b1SScott Long 			       			/*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
2269f1c579b1SScott Long 			       			/*highaddr*/BUS_SPACE_MAXADDR,
2270f1c579b1SScott Long 			       			/*filter*/NULL,
2271f1c579b1SScott Long 				   			/*filterarg*/NULL,
2272f1c579b1SScott Long 			       			/*maxsize*/((sizeof(struct _SRB) * ARCMSR_MAX_FREESRB_NUM)+0x20),
2273f1c579b1SScott Long 			       			/*nsegments*/1,
2274f1c579b1SScott Long 			       			/*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
2275f1c579b1SScott Long 			       			/*flags*/BUS_DMA_ALLOCNOW,
2276f1c579b1SScott Long 							/*lockfunc*/NULL,
2277f1c579b1SScott Long 							/*lockarg*/NULL,
2278f1c579b1SScott Long 							&pACB->srb_dmat) != 0)
2279f1c579b1SScott Long #else
2280f1c579b1SScott Long 	if (bus_dma_tag_create( /*parent_dmat*/pACB->parent_dmat,
2281f1c579b1SScott Long 		                    /*alignment*/1,
2282f1c579b1SScott Long 		                    /*boundary*/0,
2283f1c579b1SScott Long 			       			/*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
2284f1c579b1SScott Long 			       			/*highaddr*/BUS_SPACE_MAXADDR,
2285f1c579b1SScott Long 			       			/*filter*/NULL,
2286f1c579b1SScott Long 				   			/*filterarg*/NULL,
2287f1c579b1SScott Long 			       			/*maxsize*/((sizeof(struct _SRB) * ARCMSR_MAX_FREESRB_NUM)+0x20),
2288f1c579b1SScott Long 			       			/*nsegments*/1,
2289f1c579b1SScott Long 			       			/*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
2290f1c579b1SScott Long 			       			/*flags*/BUS_DMA_ALLOCNOW,
2291f1c579b1SScott Long 							&pACB->srb_dmat) != 0)
2292f1c579b1SScott Long #endif
2293f1c579b1SScott Long 	{
2294f1c579b1SScott Long 		bus_dma_tag_destroy(pACB->buffer_dmat);
2295f1c579b1SScott Long 		bus_dma_tag_destroy(pACB->parent_dmat);
2296f1c579b1SScott Long 		printf("arcmsr_initialize: pACB->srb_dmat bus_dma_tag_create .....................failure!\n");
2297f1c579b1SScott Long 		return ENXIO;
2298f1c579b1SScott Long     }
2299f1c579b1SScott Long 	/* Allocation for our srbs */
2300f1c579b1SScott Long 	if (bus_dmamem_alloc(pACB->srb_dmat, (void **)&pACB->uncacheptr, BUS_DMA_WAITOK | BUS_DMA_COHERENT, &pACB->srb_dmamap) != 0)
2301f1c579b1SScott Long 	{
2302f1c579b1SScott Long         bus_dma_tag_destroy(pACB->srb_dmat);
2303f1c579b1SScott Long 		bus_dma_tag_destroy(pACB->buffer_dmat);
2304f1c579b1SScott Long 		bus_dma_tag_destroy(pACB->parent_dmat);
2305f1c579b1SScott Long 		printf("arcmsr_initialize: pACB->srb_dmat bus_dma_tag_create ...............failure!\n");
2306f1c579b1SScott Long 		return ENXIO;
2307f1c579b1SScott Long 	}
2308f1c579b1SScott Long 	/* And permanently map them */
2309f1c579b1SScott Long 	if(bus_dmamap_load(pACB->srb_dmat, pACB->srb_dmamap,pACB->uncacheptr,(sizeof(struct _SRB) * ARCMSR_MAX_FREESRB_NUM)+0x20,arcmsr_map_freesrb, pACB, /*flags*/0))
2310f1c579b1SScott Long 	{
2311f1c579b1SScott Long         bus_dma_tag_destroy(pACB->srb_dmat);
2312f1c579b1SScott Long 		bus_dma_tag_destroy(pACB->buffer_dmat);
2313f1c579b1SScott Long 		bus_dma_tag_destroy(pACB->parent_dmat);
2314f1c579b1SScott Long 		printf("arcmsr_initialize: bus_dmamap_load................... failure!\n");
2315f1c579b1SScott Long 		return ENXIO;
2316f1c579b1SScott Long 	}
2317f1c579b1SScott Long 	pci_command=pci_read_config(dev,PCIR_COMMAND,2);
2318f1c579b1SScott Long 	pci_command |= PCIM_CMD_BUSMASTEREN;
2319f1c579b1SScott Long 	pci_command |= PCIM_CMD_PERRESPEN;
2320f1c579b1SScott Long 	pci_command |= PCIM_CMD_MWRICEN;
2321f1c579b1SScott Long 	/* Enable Busmaster/Mem */
2322f1c579b1SScott Long 	pci_command |= PCIM_CMD_MEMEN;
2323f1c579b1SScott Long 	pci_write_config(dev,PCIR_COMMAND,pci_command,2);
2324f1c579b1SScott Long 	pACB->sys_res_arcmsr=bus_alloc_resource(dev,SYS_RES_MEMORY,&rid,0,~0,0x1000,RF_ACTIVE);
2325f1c579b1SScott Long 	if(pACB->sys_res_arcmsr == NULL)
2326f1c579b1SScott Long 	{
2327f1c579b1SScott Long 		arcmsr_free_resource(pACB);
2328f1c579b1SScott Long 		printf("arcmsr_initialize: bus_alloc_resource .....................failure!\n");
2329f1c579b1SScott Long 		return ENOMEM;
2330f1c579b1SScott Long 	}
2331f1c579b1SScott Long 	if(rman_get_start(pACB->sys_res_arcmsr) <= 0)
2332f1c579b1SScott Long 	{
2333f1c579b1SScott Long 		arcmsr_free_resource(pACB);
2334f1c579b1SScott Long 		printf("arcmsr_initialize: rman_get_start ...........................failure!\n");
2335f1c579b1SScott Long         return ENXIO;
2336f1c579b1SScott Long 	}
2337f1c579b1SScott Long 	mem_base=(vm_offset_t) rman_get_virtual(pACB->sys_res_arcmsr);
2338f1c579b1SScott Long 	if(mem_base==0)
2339f1c579b1SScott Long 	{
2340f1c579b1SScott Long 		arcmsr_free_resource(pACB);
2341f1c579b1SScott Long 		printf("arcmsr_initialize: rman_get_virtual ..........................failure!\n");
2342f1c579b1SScott Long 		return ENXIO;
2343f1c579b1SScott Long 	}
2344f1c579b1SScott Long 	if(pACB->acb_flags &  ACB_F_MAPFREESRB_FAILD)
2345f1c579b1SScott Long 	{
2346f1c579b1SScott Long 		arcmsr_free_resource(pACB);
2347f1c579b1SScott Long 		printf("arcmsr_initialize: arman_get_virtual ..........................failure!\n");
2348f1c579b1SScott Long 		return ENXIO;
2349f1c579b1SScott Long 	}
2350f1c579b1SScott Long 	pACB->btag=rman_get_bustag(pACB->sys_res_arcmsr);
2351f1c579b1SScott Long 	pACB->bhandle=rman_get_bushandle(pACB->sys_res_arcmsr);
2352f1c579b1SScott Long     pACB->pmu=(PMU)mem_base;
2353f1c579b1SScott Long     pACB->acb_flags |= (ACB_F_IOCTL_WQBUFFER_CLEARED|ACB_F_IOCTL_RQBUFFER_CLEARED);
2354f1c579b1SScott Long 	pACB->acb_flags &= ~ACB_F_SCSISTOPADAPTER;
2355f1c579b1SScott Long 	arcmsr_iop_init(pACB);
2356f1c579b1SScott Long     return(0);
2357f1c579b1SScott Long }
2358f1c579b1SScott Long /*
2359f1c579b1SScott Long ************************************************************************
2360f1c579b1SScott Long **
2361f1c579b1SScott Long **        attach and init a host adapter
2362f1c579b1SScott Long **
2363f1c579b1SScott Long ************************************************************************
2364f1c579b1SScott Long */
2365f1c579b1SScott Long static LONG arcmsr_attach(device_t dev)
2366f1c579b1SScott Long {
2367f1c579b1SScott Long 	PACB pACB=device_get_softc(dev);
2368f1c579b1SScott Long 	LONG unit=device_get_unit(dev);
2369f1c579b1SScott Long 	struct ccb_setasync csa;
2370f1c579b1SScott Long 	struct cam_devq	*devq;	/* Device Queue to use for this SIM */
2371f1c579b1SScott Long 	struct resource	*irqres;
2372f1c579b1SScott Long 	int	rid;
2373f1c579b1SScott Long 
2374f1c579b1SScott Long     #if ARCMSR_DEBUG0
2375f1c579b1SScott Long     printf("arcmsr_attach .............................\n" );
2376f1c579b1SScott Long     #endif
2377f1c579b1SScott Long 
2378f1c579b1SScott Long 	if(arcmsr_initialize(dev))
2379f1c579b1SScott Long 	{
2380f1c579b1SScott Long 		printf("arcmsr_attach: arcmsr_initialize failure!\n");
2381f1c579b1SScott Long 		return ENXIO;
2382f1c579b1SScott Long 	}
2383f1c579b1SScott Long 	/* After setting up the adapter,map our interrupt */
2384f1c579b1SScott Long 	rid=0;
2385f1c579b1SScott Long 	irqres=bus_alloc_resource(dev,SYS_RES_IRQ,&rid,0,~0,1,RF_SHAREABLE | RF_ACTIVE);
2386f1c579b1SScott Long 	if(irqres == NULL || bus_setup_intr(dev,irqres,INTR_TYPE_CAM,arcmsr_interrupt,pACB,&pACB->ih))
2387f1c579b1SScott Long 	{
2388f1c579b1SScott Long 		arcmsr_free_resource(pACB);
2389f1c579b1SScott Long 		printf("arcmsr%d: unable to register interrupt handler!\n",unit);
2390f1c579b1SScott Long 		return ENXIO;
2391f1c579b1SScott Long 	}
2392f1c579b1SScott Long 	pACB->irqres=irqres;
2393f1c579b1SScott Long 	pACB->pci_dev=dev;
2394f1c579b1SScott Long 	pACB->pci_unit=unit;
2395f1c579b1SScott Long 	/*
2396f1c579b1SScott Long 	 * Now let the CAM generic SCSI layer find the SCSI devices on
2397f1c579b1SScott Long 	 * the bus *  start queue to reset to the idle loop. *
2398f1c579b1SScott Long 	 * Create device queue of SIM(s) *  (MAX_START_JOB - 1) :
2399f1c579b1SScott Long 	 * max_sim_transactions
2400f1c579b1SScott Long 	*/
2401f1c579b1SScott Long 	devq=cam_simq_alloc(ARCMSR_MAX_START_JOB);
2402f1c579b1SScott Long 	if(devq == NULL)
2403f1c579b1SScott Long 	{
2404f1c579b1SScott Long 	    arcmsr_free_resource(pACB);
2405f1c579b1SScott Long 		bus_release_resource(dev, SYS_RES_IRQ, 0, pACB->irqres);
2406f1c579b1SScott Long 		printf("arcmsr_attach: cam_simq_alloc failure!\n");
2407f1c579b1SScott Long 		return ENXIO;
2408f1c579b1SScott Long 	}
2409f1c579b1SScott Long 	pACB->psim=cam_sim_alloc(arcmsr_action,arcmsr_poll,"arcmsr",pACB,pACB->pci_unit,1,ARCMSR_MAX_OUTSTANDING_CMD,devq);
2410f1c579b1SScott Long 	if(pACB->psim == NULL)
2411f1c579b1SScott Long 	{
2412f1c579b1SScott Long 		arcmsr_free_resource(pACB);
2413f1c579b1SScott Long 		bus_release_resource(dev, SYS_RES_IRQ, 0, pACB->irqres);
2414f1c579b1SScott Long 		cam_simq_free(devq);
2415f1c579b1SScott Long 		printf("arcmsr_attach: cam_sim_alloc ..................failure!\n");
2416f1c579b1SScott Long 		return ENXIO;
2417f1c579b1SScott Long 	}
2418f1c579b1SScott Long 	if(xpt_bus_register(pACB->psim,0) != CAM_SUCCESS)
2419f1c579b1SScott Long 	{
2420f1c579b1SScott Long 		arcmsr_free_resource(pACB);
2421f1c579b1SScott Long 		bus_release_resource(dev, SYS_RES_IRQ, 0, pACB->irqres);
2422f1c579b1SScott Long 		cam_sim_free(pACB->psim,/*free_devq*/TRUE);
2423f1c579b1SScott Long 		printf("arcmsr_attach: xpt_bus_register .......................failure!\n");
2424f1c579b1SScott Long 		return ENXIO;
2425f1c579b1SScott Long 	}
2426f1c579b1SScott Long  	if(xpt_create_path(&pACB->ppath,/* periph */ NULL,cam_sim_path(pACB->psim),CAM_TARGET_WILDCARD,CAM_LUN_WILDCARD) != CAM_REQ_CMP)
2427f1c579b1SScott Long 	{
2428f1c579b1SScott Long 		arcmsr_free_resource(pACB);
2429f1c579b1SScott Long 		bus_release_resource(dev, SYS_RES_IRQ, 0, pACB->irqres);
2430f1c579b1SScott Long 		xpt_bus_deregister(cam_sim_path(pACB->psim));
2431f1c579b1SScott Long 		cam_sim_free(pACB->psim,/* free_simq */ TRUE);
2432f1c579b1SScott Long 		printf("arcmsr_attach: xpt_create_path .....................failure!\n");
2433f1c579b1SScott Long 		return ENXIO;
2434f1c579b1SScott Long 	}
2435f1c579b1SScott Long     /*
2436f1c579b1SScott Long 	****************************************************
2437f1c579b1SScott Long 	*/
2438f1c579b1SScott Long  	xpt_setup_ccb(&csa.ccb_h,pACB->ppath,/*priority*/5);
2439f1c579b1SScott Long 	csa.ccb_h.func_code=XPT_SASYNC_CB;
2440f1c579b1SScott Long 	csa.event_enable=AC_FOUND_DEVICE|AC_LOST_DEVICE;
2441f1c579b1SScott Long 	csa.callback=arcmsr_async;
2442f1c579b1SScott Long 	csa.callback_arg=pACB->psim;
2443f1c579b1SScott Long 	xpt_action((union ccb *)&csa);
2444f1c579b1SScott Long     /* Create the control device.  */
2445f1c579b1SScott Long     pACB->ioctl_dev=make_dev(&arcmsr_cdevsw, unit, UID_ROOT, GID_WHEEL /* GID_OPERATOR */, S_IRUSR | S_IWUSR, "arcmsr%d", unit);
2446f1c579b1SScott Long #if __FreeBSD_version < 503000
2447f1c579b1SScott Long 	pACB->ioctl_dev->si_drv1=pACB;
2448f1c579b1SScott Long #endif
2449f1c579b1SScott Long #if __FreeBSD_version > 500005
2450f1c579b1SScott Long 	(void)make_dev_alias(pACB->ioctl_dev, "arc%d", unit);
2451f1c579b1SScott Long #endif
2452f1c579b1SScott Long 
2453f1c579b1SScott Long #if 0
2454f1c579b1SScott Long 	#if __FreeBSD_version > 500005
2455f1c579b1SScott Long 		if(kthread_create(arcmsr_do_thread_works, pACB, &pACB->kthread_proc,0,"arcmsr%d: kthread",pACB->pci_unit))
2456f1c579b1SScott Long 		{
2457f1c579b1SScott Long 			device_printf(pACB->pci_dev,"cannot create kernel thread for this host adapetr\n");
2458f1c579b1SScott Long 			xpt_bus_deregister(cam_sim_path(pACB->psim));
2459f1c579b1SScott Long 			cam_sim_free(pACB->psim,/* free_simq */ TRUE);
2460f1c579b1SScott Long 			panic("arcmsr plunge kernel thread fail");
2461f1c579b1SScott Long 		}
2462f1c579b1SScott Long 	#else
2463f1c579b1SScott Long 		if(kthread_create(arcmsr_do_thread_works, pACB, &pACB->kthread_proc,"arcmsr%d: kthread", pACB->pci_unit))
2464f1c579b1SScott Long 		{
2465f1c579b1SScott Long 			device_printf(pACB->pci_dev,"cannot create kernel thread for this host adapetr\n");
2466f1c579b1SScott Long 			xpt_bus_deregister(cam_sim_path(pACB->psim));
2467f1c579b1SScott Long 			cam_sim_free(pACB->psim,/* free_simq */ TRUE);
2468f1c579b1SScott Long 			panic("arcmsr plunge kernel thread fail");
2469f1c579b1SScott Long 		}
2470f1c579b1SScott Long 	#endif
2471f1c579b1SScott Long #endif
2472f1c579b1SScott Long  	return 0;
2473f1c579b1SScott Long }
2474f1c579b1SScott Long /*
2475f1c579b1SScott Long ************************************************************************
2476f1c579b1SScott Long **
2477f1c579b1SScott Long **
2478f1c579b1SScott Long **
2479f1c579b1SScott Long ************************************************************************
2480f1c579b1SScott Long */
2481f1c579b1SScott Long static LONG arcmsr_probe(device_t dev)
2482f1c579b1SScott Long {
2483f1c579b1SScott Long 	ULONG id;
2484f1c579b1SScott Long 	#if ARCMSR_DEBUG0
2485f1c579b1SScott Long 	printf("arcmsr_probe................. \n");
2486f1c579b1SScott Long 	#endif
2487f1c579b1SScott Long     switch(id=pci_get_devid(dev))
2488f1c579b1SScott Long 	{
2489f1c579b1SScott Long 	case PCIDevVenIDARC1110:
2490f1c579b1SScott Long 		device_set_desc(dev,"ARECA ARC1110 PCI-X 4 PORTS SATA RAID CONTROLLER \n" ARCMSR_DRIVER_VERSION );
2491f1c579b1SScott Long 	    return 0;
2492f1c579b1SScott Long     case PCIDevVenIDARC1120:
2493f1c579b1SScott Long 		device_set_desc(dev,"ARECA ARC1120 PCI-X 8 PORTS SATA RAID CONTROLLER (RAID6-ENGINE Inside) \n" ARCMSR_DRIVER_VERSION);
2494f1c579b1SScott Long 		return 0;
2495f1c579b1SScott Long     case PCIDevVenIDARC1130:
2496f1c579b1SScott Long 		device_set_desc(dev,"ARECA ARC1130 PCI-X 12 PORTS SATA RAID CONTROLLER (RAID6-ENGINE Inside) \n" ARCMSR_DRIVER_VERSION);
2497f1c579b1SScott Long 		return 0;
2498f1c579b1SScott Long     case PCIDevVenIDARC1160:
2499f1c579b1SScott Long 		device_set_desc(dev,"ARECA ARC1160 PCI-X 16 PORTS SATA RAID CONTROLLER (RAID6-ENGINE Inside) \n" ARCMSR_DRIVER_VERSION);
2500f1c579b1SScott Long 		return 0;
2501f1c579b1SScott Long     case PCIDevVenIDARC1210:
2502f1c579b1SScott Long 		device_set_desc(dev,"ARECA ARC1210 PCI-EXPRESS 4 PORTS SATA RAID CONTROLLER \n" ARCMSR_DRIVER_VERSION);
2503f1c579b1SScott Long 		return 0;
2504f1c579b1SScott Long     case PCIDevVenIDARC1220:
2505f1c579b1SScott Long 		device_set_desc(dev,"ARECA ARC1220 PCI-EXPRESS 8 PORTS SATA RAID CONTROLLER (RAID6-ENGINE Inside) \n" ARCMSR_DRIVER_VERSION);
2506f1c579b1SScott Long 		return 0;
2507f1c579b1SScott Long    case PCIDevVenIDARC1230:
2508f1c579b1SScott Long 		device_set_desc(dev,"ARECA ARC1230 PCI-EXPRESS 12 PORTS SATA RAID CONTROLLER (RAID6-ENGINE Inside) \n" ARCMSR_DRIVER_VERSION);
2509f1c579b1SScott Long 		return 0;
2510f1c579b1SScott Long     case PCIDevVenIDARC1260:
2511f1c579b1SScott Long 		device_set_desc(dev,"ARECA ARC1260 PCI-EXPRESS 16 PORTS SATA RAID CONTROLLER (RAID6-ENGINE Inside) \n" ARCMSR_DRIVER_VERSION);
2512f1c579b1SScott Long 		return 0;
2513f1c579b1SScott Long 	}
2514f1c579b1SScott Long 	return ENXIO;
2515f1c579b1SScott Long }
2516f1c579b1SScott Long /*
2517f1c579b1SScott Long ************************************************************************
2518f1c579b1SScott Long **
2519f1c579b1SScott Long **
2520f1c579b1SScott Long **
2521f1c579b1SScott Long ************************************************************************
2522f1c579b1SScott Long */
2523f1c579b1SScott Long static VOID arcmsr_shutdown(device_t dev)
2524f1c579b1SScott Long {
2525f1c579b1SScott Long 	LONG  i,abort_cmd_cnt=0;
2526f1c579b1SScott Long 	ULONG s,intmask_org;
2527f1c579b1SScott Long 	PSRB pSRB;
2528f1c579b1SScott Long     PACB pACB=device_get_softc(dev);
2529f1c579b1SScott Long 
2530f1c579b1SScott Long 	#if ARCMSR_DEBUG0
2531f1c579b1SScott Long 	printf("arcmsr_shutdown................. \n");
2532f1c579b1SScott Long 	#endif
2533f1c579b1SScott Long 	s=splcam();
2534f1c579b1SScott Long     /* disable all outbound interrupt */
2535f1c579b1SScott Long     intmask_org=CHIP_REG_READ32(&pACB->pmu->outbound_intmask);
2536f1c579b1SScott Long     CHIP_REG_WRITE32(&pACB->pmu->outbound_intmask,(intmask_org|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE));
2537f1c579b1SScott Long 	/* stop adapter background rebuild */
2538f1c579b1SScott Long 	arcmsr_stop_adapter_bgrb(pACB);
2539f1c579b1SScott Long 	if(arcmsr_wait_msgint_ready(pACB)!=TRUE)
2540f1c579b1SScott Long 	{
2541f1c579b1SScott Long 		printf("arcmsr_pcidev_disattach: wait 'stop adapter rebulid' timeout.... \n");
2542f1c579b1SScott Long 	}
2543f1c579b1SScott Long 	arcmsr_flush_adapter_cache(pACB);
2544f1c579b1SScott Long 	if(arcmsr_wait_msgint_ready(pACB)!=TRUE)
2545f1c579b1SScott Long 	{
2546f1c579b1SScott Long 		printf("arcmsr_pcidev_disattach: wait 'flush adapter cache' timeout.... \n");
2547f1c579b1SScott Long 	}
2548f1c579b1SScott Long 	/* abort all outstanding command */
2549f1c579b1SScott Long 	pACB->acb_flags |= ACB_F_SCSISTOPADAPTER;
2550f1c579b1SScott Long 	pACB->acb_flags &= ~ACB_F_IOP_INITED;
2551f1c579b1SScott Long 	if(pACB->srboutstandingcount!=0)
2552f1c579b1SScott Long 	{
2553f1c579b1SScott Long 		PSRB pfreesrb;
2554f1c579b1SScott Long 	#if ARCMSR_DEBUG0
2555f1c579b1SScott Long 	printf("arcmsr_pcidev_disattach: .....pACB->srboutstandingcount!=0 \n");
2556f1c579b1SScott Long     #endif
2557f1c579b1SScott Long 		/* Q back all outstanding srb into wait exec psrb Q*/
2558f1c579b1SScott Long         pfreesrb=pACB->pfreesrb;
2559f1c579b1SScott Long 		for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++)
2560f1c579b1SScott Long 		{
2561f1c579b1SScott Long 	    	pSRB=&pfreesrb[i];
2562f1c579b1SScott Long 			if(pSRB->startdone==ARCMSR_SRB_START)
2563f1c579b1SScott Long 			{
2564f1c579b1SScott Long 				pSRB->srb_flags|=SRB_FLAG_MASTER_ABORTED;
2565f1c579b1SScott Long 				pSRB->pccb->ccb_h.status=CAM_REQ_ABORTED;
2566f1c579b1SScott Long 				abort_cmd_cnt++;
2567f1c579b1SScott Long 			}
2568f1c579b1SScott Long 		}
2569f1c579b1SScott Long 		if(abort_cmd_cnt!=0)
2570f1c579b1SScott Long 		{
2571f1c579b1SScott Long 	#if ARCMSR_DEBUG0
2572f1c579b1SScott Long 	printf("arcmsr_pcidev_disattach: .....abort_cmd_cnt!=0 \n");
2573f1c579b1SScott Long     #endif
2574f1c579b1SScott Long 			arcmsr_abort_allcmd(pACB);
2575f1c579b1SScott Long 			if(arcmsr_wait_msgint_ready(pACB)!=TRUE)
2576f1c579b1SScott Long 			{
2577f1c579b1SScott Long 				printf("arcmsr_pcidev_disattach: wait 'abort all outstanding command' timeout.................in \n");
2578f1c579b1SScott Long 			}
2579f1c579b1SScott Long 		}
2580f1c579b1SScott Long 		atomic_set_int(&pACB->srboutstandingcount,0);
2581f1c579b1SScott Long  	}
2582f1c579b1SScott Long 	if(pACB->srbwait2gocount!=0)
2583f1c579b1SScott Long 	{	/*remove first wait2go srb and abort it*/
2584f1c579b1SScott Long 		for(i=0;i<ARCMSR_MAX_OUTSTANDING_CMD;i++)
2585f1c579b1SScott Long 		{
2586f1c579b1SScott Long 			pSRB=pACB->psrbwait2go[i];
2587f1c579b1SScott Long 			if(pSRB!=NULL)
2588f1c579b1SScott Long 			{
2589f1c579b1SScott Long 				pACB->psrbwait2go[i]=NULL;
2590f1c579b1SScott Long 				atomic_subtract_int(&pACB->srbwait2gocount,1);
2591f1c579b1SScott Long 				pSRB->pccb->ccb_h.status=CAM_REQ_ABORTED;
2592f1c579b1SScott Long 				arcmsr_srb_complete(pSRB);
2593f1c579b1SScott Long 			}
2594f1c579b1SScott Long 		}
2595f1c579b1SScott Long 	}
2596f1c579b1SScott Long 	splx(s);
2597f1c579b1SScott Long 	pACB->acb_flags |= ACB_F_STOP_THREAD;
2598f1c579b1SScott Long 	wakeup(pACB->kthread_proc);/* signal to kernel thread do_dpcQ: "stop thread" */
2599f1c579b1SScott Long     return;
2600f1c579b1SScott Long }
2601f1c579b1SScott Long /*
2602f1c579b1SScott Long ************************************************************************
2603f1c579b1SScott Long **
2604f1c579b1SScott Long **
2605f1c579b1SScott Long **
2606f1c579b1SScott Long ************************************************************************
2607f1c579b1SScott Long */
2608f1c579b1SScott Long static LONG arcmsr_detach(device_t dev)
2609f1c579b1SScott Long {
2610f1c579b1SScott Long 	PACB pACB=device_get_softc(dev);
2611f1c579b1SScott Long 
2612f1c579b1SScott Long 	arcmsr_shutdown(dev);
2613f1c579b1SScott Long 	arcmsr_free_resource(pACB);
2614f1c579b1SScott Long 	bus_release_resource(dev, SYS_RES_MEMORY, PCIR_MAPS, pACB->sys_res_arcmsr);
2615f1c579b1SScott Long 	bus_teardown_intr(dev, pACB->irqres, pACB->ih);
2616f1c579b1SScott Long 	bus_release_resource(dev, SYS_RES_IRQ, 0, pACB->irqres);
2617f1c579b1SScott Long 	xpt_async(AC_LOST_DEVICE, pACB->ppath, NULL);
2618f1c579b1SScott Long 	xpt_free_path(pACB->ppath);
2619f1c579b1SScott Long 	xpt_bus_deregister(cam_sim_path(pACB->psim));
2620f1c579b1SScott Long 	cam_sim_free(pACB->psim, TRUE);
2621f1c579b1SScott Long 	return (0);
2622f1c579b1SScott Long }
2623f1c579b1SScott Long 
2624f1c579b1SScott Long 
2625f1c579b1SScott Long 
2626