1169412Sscottl/*
2175942Sscottl * HighPoint RR3xxx/4xxx RAID Driver for FreeBSD
3242214Sdelphij * Copyright (C) 2007-2012 HighPoint Technologies, Inc. All Rights Reserved.
4175942Sscottl *
5169412Sscottl * Redistribution and use in source and binary forms, with or without
6169412Sscottl * modification, are permitted provided that the following conditions
7169412Sscottl * are met:
8169412Sscottl * 1. Redistributions of source code must retain the above copyright
9169412Sscottl *    notice, this list of conditions and the following disclaimer.
10169412Sscottl * 2. Redistributions in binary form must reproduce the above copyright
11169412Sscottl *    notice, this list of conditions and the following disclaimer in the
12169412Sscottl *    documentation and/or other materials provided with the distribution.
13169412Sscottl *
14169412Sscottl * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15169412Sscottl * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16169412Sscottl * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17169412Sscottl * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18169412Sscottl * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19169412Sscottl * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20169412Sscottl * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21169412Sscottl * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22169412Sscottl * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23169412Sscottl * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24169412Sscottl * SUCH DAMAGE.
25169412Sscottl */
26175942Sscottl
27169412Sscottl#include <sys/cdefs.h>
28169412Sscottl__FBSDID("$FreeBSD$");
29169412Sscottl
30169412Sscottl#include <sys/param.h>
31169412Sscottl#include <sys/types.h>
32169412Sscottl#include <sys/cons.h>
33169412Sscottl#if (__FreeBSD_version >= 500000)
34169412Sscottl#include <sys/time.h>
35169412Sscottl#include <sys/systm.h>
36169412Sscottl#else
37169412Sscottl#include <machine/clock.h>
38169412Sscottl#endif
39169412Sscottl
40169412Sscottl#include <sys/stat.h>
41169412Sscottl#include <sys/malloc.h>
42169412Sscottl#include <sys/conf.h>
43169412Sscottl#include <sys/libkern.h>
44169412Sscottl#include <sys/kernel.h>
45169412Sscottl
46169412Sscottl#if (__FreeBSD_version >= 500000)
47169412Sscottl#include <sys/kthread.h>
48169412Sscottl#include <sys/mutex.h>
49169412Sscottl#include <sys/module.h>
50169412Sscottl#endif
51169412Sscottl
52169412Sscottl#include <sys/eventhandler.h>
53169412Sscottl#include <sys/bus.h>
54169412Sscottl#include <sys/taskqueue.h>
55169412Sscottl#include <sys/ioccom.h>
56169412Sscottl
57169412Sscottl#include <machine/resource.h>
58169412Sscottl#include <machine/bus.h>
59169412Sscottl#include <machine/stdarg.h>
60169412Sscottl#include <sys/rman.h>
61169412Sscottl
62169412Sscottl#include <vm/vm.h>
63169412Sscottl#include <vm/pmap.h>
64169412Sscottl
65169412Sscottl#if (__FreeBSD_version >= 500000)
66169412Sscottl#include <dev/pci/pcireg.h>
67169412Sscottl#include <dev/pci/pcivar.h>
68169412Sscottl#else
69169412Sscottl#include <pci/pcivar.h>
70169412Sscottl#include <pci/pcireg.h>
71169412Sscottl#endif
72169412Sscottl
73169412Sscottl#if (__FreeBSD_version <= 500043)
74169412Sscottl#include <sys/devicestat.h>
75169412Sscottl#endif
76169412Sscottl
77169412Sscottl#include <cam/cam.h>
78169412Sscottl#include <cam/cam_ccb.h>
79169412Sscottl#include <cam/cam_sim.h>
80169412Sscottl#include <cam/cam_xpt_sim.h>
81169412Sscottl#include <cam/cam_debug.h>
82169412Sscottl#include <cam/cam_periph.h>
83169412Sscottl#include <cam/scsi/scsi_all.h>
84169412Sscottl#include <cam/scsi/scsi_message.h>
85169412Sscottl
86169412Sscottl#if (__FreeBSD_version < 500043)
87169412Sscottl#include <sys/bus_private.h>
88169412Sscottl#endif
89169412Sscottl
90169412Sscottl#include <dev/hptiop/hptiop.h>
91169412Sscottl
92242214Sdelphijstatic const char driver_name[] = "hptiop";
93252884Sdelphijstatic const char driver_version[] = "v1.9";
94169412Sscottl
95169412Sscottlstatic devclass_t hptiop_devclass;
96169412Sscottl
97175942Sscottlstatic int hptiop_send_sync_msg(struct hpt_iop_hba *hba,
98175942Sscottl				u_int32_t msg, u_int32_t millisec);
99175942Sscottlstatic void hptiop_request_callback_itl(struct hpt_iop_hba *hba,
100175942Sscottl							u_int32_t req);
101175942Sscottlstatic void hptiop_request_callback_mv(struct hpt_iop_hba *hba, u_int64_t req);
102242214Sdelphijstatic void hptiop_request_callback_mvfrey(struct hpt_iop_hba *hba,
103242214Sdelphij							u_int32_t req);
104175942Sscottlstatic void hptiop_os_message_callback(struct hpt_iop_hba *hba, u_int32_t msg);
105175942Sscottlstatic int  hptiop_do_ioctl_itl(struct hpt_iop_hba *hba,
106175942Sscottl				struct hpt_iop_ioctl_param *pParams);
107175942Sscottlstatic int  hptiop_do_ioctl_mv(struct hpt_iop_hba *hba,
108175942Sscottl				struct hpt_iop_ioctl_param *pParams);
109242214Sdelphijstatic int  hptiop_do_ioctl_mvfrey(struct hpt_iop_hba *hba,
110242214Sdelphij				struct hpt_iop_ioctl_param *pParams);
111175942Sscottlstatic int  hptiop_rescan_bus(struct hpt_iop_hba *hba);
112175942Sscottlstatic int hptiop_alloc_pci_res_itl(struct hpt_iop_hba *hba);
113175942Sscottlstatic int hptiop_alloc_pci_res_mv(struct hpt_iop_hba *hba);
114242214Sdelphijstatic int hptiop_alloc_pci_res_mvfrey(struct hpt_iop_hba *hba);
115175942Sscottlstatic int hptiop_get_config_itl(struct hpt_iop_hba *hba,
116175942Sscottl				struct hpt_iop_request_get_config *config);
117175942Sscottlstatic int hptiop_get_config_mv(struct hpt_iop_hba *hba,
118175942Sscottl				struct hpt_iop_request_get_config *config);
119242214Sdelphijstatic int hptiop_get_config_mvfrey(struct hpt_iop_hba *hba,
120242214Sdelphij				struct hpt_iop_request_get_config *config);
121175942Sscottlstatic int hptiop_set_config_itl(struct hpt_iop_hba *hba,
122175942Sscottl				struct hpt_iop_request_set_config *config);
123175942Sscottlstatic int hptiop_set_config_mv(struct hpt_iop_hba *hba,
124175942Sscottl				struct hpt_iop_request_set_config *config);
125242214Sdelphijstatic int hptiop_set_config_mvfrey(struct hpt_iop_hba *hba,
126242214Sdelphij				struct hpt_iop_request_set_config *config);
127175942Sscottlstatic int hptiop_internal_memalloc_mv(struct hpt_iop_hba *hba);
128242214Sdelphijstatic int hptiop_internal_memalloc_mvfrey(struct hpt_iop_hba *hba);
129242214Sdelphijstatic int hptiop_internal_memfree_itl(struct hpt_iop_hba *hba);
130175942Sscottlstatic int hptiop_internal_memfree_mv(struct hpt_iop_hba *hba);
131242214Sdelphijstatic int hptiop_internal_memfree_mvfrey(struct hpt_iop_hba *hba);
132175942Sscottlstatic int  hptiop_post_ioctl_command_itl(struct hpt_iop_hba *hba,
133175942Sscottl			u_int32_t req32, struct hpt_iop_ioctl_param *pParams);
134175942Sscottlstatic int  hptiop_post_ioctl_command_mv(struct hpt_iop_hba *hba,
135175942Sscottl				struct hpt_iop_request_ioctl_command *req,
136175942Sscottl				struct hpt_iop_ioctl_param *pParams);
137242214Sdelphijstatic int  hptiop_post_ioctl_command_mvfrey(struct hpt_iop_hba *hba,
138242214Sdelphij				struct hpt_iop_request_ioctl_command *req,
139242214Sdelphij				struct hpt_iop_ioctl_param *pParams);
140175942Sscottlstatic void hptiop_post_req_itl(struct hpt_iop_hba *hba,
141175942Sscottl				struct hpt_iop_srb *srb,
142175942Sscottl				bus_dma_segment_t *segs, int nsegs);
143175942Sscottlstatic void hptiop_post_req_mv(struct hpt_iop_hba *hba,
144175942Sscottl				struct hpt_iop_srb *srb,
145175942Sscottl				bus_dma_segment_t *segs, int nsegs);
146242214Sdelphijstatic void hptiop_post_req_mvfrey(struct hpt_iop_hba *hba,
147242214Sdelphij				struct hpt_iop_srb *srb,
148242214Sdelphij				bus_dma_segment_t *segs, int nsegs);
149175942Sscottlstatic void hptiop_post_msg_itl(struct hpt_iop_hba *hba, u_int32_t msg);
150175942Sscottlstatic void hptiop_post_msg_mv(struct hpt_iop_hba *hba, u_int32_t msg);
151242214Sdelphijstatic void hptiop_post_msg_mvfrey(struct hpt_iop_hba *hba, u_int32_t msg);
152175942Sscottlstatic void hptiop_enable_intr_itl(struct hpt_iop_hba *hba);
153175942Sscottlstatic void hptiop_enable_intr_mv(struct hpt_iop_hba *hba);
154242214Sdelphijstatic void hptiop_enable_intr_mvfrey(struct hpt_iop_hba *hba);
155175942Sscottlstatic void hptiop_disable_intr_itl(struct hpt_iop_hba *hba);
156175942Sscottlstatic void hptiop_disable_intr_mv(struct hpt_iop_hba *hba);
157242214Sdelphijstatic void hptiop_disable_intr_mvfrey(struct hpt_iop_hba *hba);
158175942Sscottlstatic void hptiop_free_srb(struct hpt_iop_hba *hba, struct hpt_iop_srb *srb);
159175942Sscottlstatic int  hptiop_os_query_remove_device(struct hpt_iop_hba *hba, int tid);
160169412Sscottlstatic int  hptiop_probe(device_t dev);
161169412Sscottlstatic int  hptiop_attach(device_t dev);
162169412Sscottlstatic int  hptiop_detach(device_t dev);
163169412Sscottlstatic int  hptiop_shutdown(device_t dev);
164169412Sscottlstatic void hptiop_action(struct cam_sim *sim, union ccb *ccb);
165169412Sscottlstatic void hptiop_poll(struct cam_sim *sim);
166175942Sscottlstatic void hptiop_async(void *callback_arg, u_int32_t code,
167175942Sscottl					struct cam_path *path, void *arg);
168169412Sscottlstatic void hptiop_pci_intr(void *arg);
169175942Sscottlstatic void hptiop_release_resource(struct hpt_iop_hba *hba);
170242214Sdelphijstatic void hptiop_reset_adapter(void *argv);
171169412Sscottlstatic d_open_t hptiop_open;
172169412Sscottlstatic d_close_t hptiop_close;
173169412Sscottlstatic d_ioctl_t hptiop_ioctl;
174169412Sscottl
175169412Sscottlstatic struct cdevsw hptiop_cdevsw = {
176169412Sscottl	.d_open = hptiop_open,
177169412Sscottl	.d_close = hptiop_close,
178169412Sscottl	.d_ioctl = hptiop_ioctl,
179169412Sscottl	.d_name = driver_name,
180169412Sscottl#if __FreeBSD_version>=503000
181169412Sscottl	.d_version = D_VERSION,
182169412Sscottl#endif
183169412Sscottl#if (__FreeBSD_version>=503000 && __FreeBSD_version<600034)
184169412Sscottl	.d_flags = D_NEEDGIANT,
185169412Sscottl#endif
186169412Sscottl#if __FreeBSD_version<600034
187169412Sscottl#if __FreeBSD_version>=501000
188169412Sscottl	.d_maj = MAJOR_AUTO,
189169412Sscottl#else
190169412Sscottl	.d_maj = HPT_DEV_MAJOR,
191169412Sscottl#endif
192169412Sscottl#endif
193169412Sscottl};
194169412Sscottl
195169412Sscottl#if __FreeBSD_version < 503000
196169412Sscottl#define hba_from_dev(dev) ((struct hpt_iop_hba *)(dev)->si_drv1)
197169412Sscottl#else
198169412Sscottl#define hba_from_dev(dev) \
199183397Sed	((struct hpt_iop_hba *)devclass_get_softc(hptiop_devclass, dev2unit(dev)))
200169412Sscottl#endif
201169412Sscottl
202175942Sscottl#define BUS_SPACE_WRT4_ITL(offset, value) bus_space_write_4(hba->bar0t,\
203175942Sscottl		hba->bar0h, offsetof(struct hpt_iopmu_itl, offset), (value))
204175942Sscottl#define BUS_SPACE_RD4_ITL(offset) bus_space_read_4(hba->bar0t,\
205175942Sscottl		hba->bar0h, offsetof(struct hpt_iopmu_itl, offset))
206175942Sscottl
207175942Sscottl#define BUS_SPACE_WRT4_MV0(offset, value) bus_space_write_4(hba->bar0t,\
208175942Sscottl		hba->bar0h, offsetof(struct hpt_iopmv_regs, offset), value)
209175942Sscottl#define BUS_SPACE_RD4_MV0(offset) bus_space_read_4(hba->bar0t,\
210175942Sscottl		hba->bar0h, offsetof(struct hpt_iopmv_regs, offset))
211175942Sscottl#define BUS_SPACE_WRT4_MV2(offset, value) bus_space_write_4(hba->bar2t,\
212175942Sscottl		hba->bar2h, offsetof(struct hpt_iopmu_mv, offset), value)
213175942Sscottl#define BUS_SPACE_RD4_MV2(offset) bus_space_read_4(hba->bar2t,\
214175942Sscottl		hba->bar2h, offsetof(struct hpt_iopmu_mv, offset))
215175942Sscottl
216242214Sdelphij#define BUS_SPACE_WRT4_MVFREY2(offset, value) bus_space_write_4(hba->bar2t,\
217242214Sdelphij		hba->bar2h, offsetof(struct hpt_iopmu_mvfrey, offset), value)
218242214Sdelphij#define BUS_SPACE_RD4_MVFREY2(offset) bus_space_read_4(hba->bar2t,\
219242214Sdelphij		hba->bar2h, offsetof(struct hpt_iopmu_mvfrey, offset))
220242214Sdelphij
221169412Sscottlstatic int hptiop_open(ioctl_dev_t dev, int flags,
222169412Sscottl					int devtype, ioctl_thread_t proc)
223169412Sscottl{
224175942Sscottl	struct hpt_iop_hba *hba = hba_from_dev(dev);
225169412Sscottl
226169412Sscottl	if (hba==NULL)
227169412Sscottl		return ENXIO;
228169412Sscottl	if (hba->flag & HPT_IOCTL_FLAG_OPEN)
229169412Sscottl		return EBUSY;
230169412Sscottl	hba->flag |= HPT_IOCTL_FLAG_OPEN;
231169412Sscottl	return 0;
232169412Sscottl}
233169412Sscottl
234169412Sscottlstatic int hptiop_close(ioctl_dev_t dev, int flags,
235169412Sscottl					int devtype, ioctl_thread_t proc)
236169412Sscottl{
237175942Sscottl	struct hpt_iop_hba *hba = hba_from_dev(dev);
238169412Sscottl	hba->flag &= ~(u_int32_t)HPT_IOCTL_FLAG_OPEN;
239169412Sscottl	return 0;
240169412Sscottl}
241169412Sscottl
242169412Sscottlstatic int hptiop_ioctl(ioctl_dev_t dev, u_long cmd, caddr_t data,
243169412Sscottl					int flags, ioctl_thread_t proc)
244169412Sscottl{
245169412Sscottl	int ret = EFAULT;
246175942Sscottl	struct hpt_iop_hba *hba = hba_from_dev(dev);
247169412Sscottl
248169412Sscottl#if (__FreeBSD_version >= 500000)
249169412Sscottl	mtx_lock(&Giant);
250169412Sscottl#endif
251169412Sscottl
252169412Sscottl	switch (cmd) {
253169412Sscottl	case HPT_DO_IOCONTROL:
254175942Sscottl		ret = hba->ops->do_ioctl(hba,
255175942Sscottl				(struct hpt_iop_ioctl_param *)data);
256169412Sscottl		break;
257169412Sscottl	case HPT_SCAN_BUS:
258169412Sscottl		ret = hptiop_rescan_bus(hba);
259169412Sscottl		break;
260169412Sscottl	}
261169412Sscottl
262169412Sscottl#if (__FreeBSD_version >= 500000)
263169412Sscottl	mtx_unlock(&Giant);
264169412Sscottl#endif
265169412Sscottl
266169412Sscottl	return ret;
267169412Sscottl}
268169412Sscottl
269175942Sscottlstatic u_int64_t hptiop_mv_outbound_read(struct hpt_iop_hba *hba)
270169412Sscottl{
271175942Sscottl	u_int64_t p;
272175942Sscottl	u_int32_t outbound_tail = BUS_SPACE_RD4_MV2(outbound_tail);
273175942Sscottl	u_int32_t outbound_head = BUS_SPACE_RD4_MV2(outbound_head);
274175942Sscottl
275175942Sscottl	if (outbound_tail != outbound_head) {
276175942Sscottl		bus_space_read_region_4(hba->bar2t, hba->bar2h,
277175942Sscottl			offsetof(struct hpt_iopmu_mv,
278175942Sscottl				outbound_q[outbound_tail]),
279175942Sscottl			(u_int32_t *)&p, 2);
280175942Sscottl
281175942Sscottl		outbound_tail++;
282175942Sscottl
283175942Sscottl		if (outbound_tail == MVIOP_QUEUE_LEN)
284175942Sscottl			outbound_tail = 0;
285175942Sscottl
286175942Sscottl		BUS_SPACE_WRT4_MV2(outbound_tail, outbound_tail);
287175942Sscottl		return p;
288175942Sscottl	} else
289175942Sscottl		return 0;
290169412Sscottl}
291169412Sscottl
292175942Sscottlstatic void hptiop_mv_inbound_write(u_int64_t p, struct hpt_iop_hba *hba)
293169412Sscottl{
294175942Sscottl	u_int32_t inbound_head = BUS_SPACE_RD4_MV2(inbound_head);
295175942Sscottl	u_int32_t head = inbound_head + 1;
296175942Sscottl
297175942Sscottl	if (head == MVIOP_QUEUE_LEN)
298175942Sscottl		head = 0;
299175942Sscottl
300175942Sscottl	bus_space_write_region_4(hba->bar2t, hba->bar2h,
301175942Sscottl			offsetof(struct hpt_iopmu_mv, inbound_q[inbound_head]),
302175942Sscottl			(u_int32_t *)&p, 2);
303175942Sscottl	BUS_SPACE_WRT4_MV2(inbound_head, head);
304175942Sscottl	BUS_SPACE_WRT4_MV0(inbound_doorbell, MVIOP_MU_INBOUND_INT_POSTQUEUE);
305169412Sscottl}
306169412Sscottl
307175942Sscottlstatic void hptiop_post_msg_itl(struct hpt_iop_hba *hba, u_int32_t msg)
308169412Sscottl{
309175942Sscottl	BUS_SPACE_WRT4_ITL(inbound_msgaddr0, msg);
310175942Sscottl	BUS_SPACE_RD4_ITL(outbound_intstatus);
311169412Sscottl}
312169412Sscottl
313175942Sscottlstatic void hptiop_post_msg_mv(struct hpt_iop_hba *hba, u_int32_t msg)
314169412Sscottl{
315175942Sscottl
316175942Sscottl	BUS_SPACE_WRT4_MV2(inbound_msg, msg);
317175942Sscottl	BUS_SPACE_WRT4_MV0(inbound_doorbell, MVIOP_MU_INBOUND_INT_MSG);
318175942Sscottl
319175942Sscottl	BUS_SPACE_RD4_MV0(outbound_intmask);
320169412Sscottl}
321169412Sscottl
322242214Sdelphijstatic void hptiop_post_msg_mvfrey(struct hpt_iop_hba *hba, u_int32_t msg)
323242214Sdelphij{
324242214Sdelphij	BUS_SPACE_WRT4_MVFREY2(f0_to_cpu_msg_a, msg);
325242214Sdelphij	BUS_SPACE_RD4_MVFREY2(f0_to_cpu_msg_a);
326242214Sdelphij}
327242214Sdelphij
328175942Sscottlstatic int hptiop_wait_ready_itl(struct hpt_iop_hba * hba, u_int32_t millisec)
329169412Sscottl{
330169412Sscottl	u_int32_t req=0;
331169412Sscottl	int i;
332169412Sscottl
333169412Sscottl	for (i = 0; i < millisec; i++) {
334175942Sscottl		req = BUS_SPACE_RD4_ITL(inbound_queue);
335169412Sscottl		if (req != IOPMU_QUEUE_EMPTY)
336169412Sscottl			break;
337169412Sscottl		DELAY(1000);
338169412Sscottl	}
339169412Sscottl
340169412Sscottl	if (req!=IOPMU_QUEUE_EMPTY) {
341175942Sscottl		BUS_SPACE_WRT4_ITL(outbound_queue, req);
342175942Sscottl		BUS_SPACE_RD4_ITL(outbound_intstatus);
343169412Sscottl		return 0;
344169412Sscottl	}
345169412Sscottl
346169412Sscottl	return -1;
347169412Sscottl}
348169412Sscottl
349175942Sscottlstatic int hptiop_wait_ready_mv(struct hpt_iop_hba * hba, u_int32_t millisec)
350169412Sscottl{
351175942Sscottl	if (hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_NOP, millisec))
352175942Sscottl		return -1;
353175942Sscottl
354175942Sscottl	return 0;
355175942Sscottl}
356175942Sscottl
357242214Sdelphijstatic int hptiop_wait_ready_mvfrey(struct hpt_iop_hba * hba,
358242214Sdelphij							u_int32_t millisec)
359242214Sdelphij{
360242214Sdelphij	if (hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_NOP, millisec))
361242214Sdelphij		return -1;
362242214Sdelphij
363242214Sdelphij	return 0;
364242214Sdelphij}
365242214Sdelphij
366175942Sscottlstatic void hptiop_request_callback_itl(struct hpt_iop_hba * hba,
367175942Sscottl							u_int32_t index)
368175942Sscottl{
369175942Sscottl	struct hpt_iop_srb *srb;
370175942Sscottl	struct hpt_iop_request_scsi_command *req=0;
371175942Sscottl	union ccb *ccb;
372175942Sscottl	u_int8_t *cdb;
373175942Sscottl	u_int32_t result, temp, dxfer;
374175942Sscottl	u_int64_t temp64;
375175942Sscottl
376175942Sscottl	if (index & IOPMU_QUEUE_MASK_HOST_BITS) { /*host req*/
377175942Sscottl		if (hba->firmware_version > 0x01020000 ||
378175942Sscottl			hba->interface_version > 0x01020000) {
379175942Sscottl			srb = hba->srb[index & ~(u_int32_t)
380175942Sscottl				(IOPMU_QUEUE_ADDR_HOST_BIT
381175942Sscottl				| IOPMU_QUEUE_REQUEST_RESULT_BIT)];
382175942Sscottl			req = (struct hpt_iop_request_scsi_command *)srb;
383175942Sscottl			if (index & IOPMU_QUEUE_REQUEST_RESULT_BIT)
384175942Sscottl				result = IOP_RESULT_SUCCESS;
385175942Sscottl			else
386175942Sscottl				result = req->header.result;
387175942Sscottl		} else {
388175942Sscottl			srb = hba->srb[index &
389175942Sscottl				~(u_int32_t)IOPMU_QUEUE_ADDR_HOST_BIT];
390175942Sscottl			req = (struct hpt_iop_request_scsi_command *)srb;
391175942Sscottl			result = req->header.result;
392175942Sscottl		}
393175942Sscottl		dxfer = req->dataxfer_length;
394175942Sscottl		goto srb_complete;
395175942Sscottl	}
396175942Sscottl
397175942Sscottl	/*iop req*/
398175942Sscottl	temp = bus_space_read_4(hba->bar0t, hba->bar0h, index +
399175942Sscottl		offsetof(struct hpt_iop_request_header, type));
400175942Sscottl	result = bus_space_read_4(hba->bar0t, hba->bar0h, index +
401175942Sscottl		offsetof(struct hpt_iop_request_header, result));
402175942Sscottl	switch(temp) {
403175942Sscottl	case IOP_REQUEST_TYPE_IOCTL_COMMAND:
404175942Sscottl	{
405175942Sscottl		temp64 = 0;
406175942Sscottl		bus_space_write_region_4(hba->bar0t, hba->bar0h, index +
407175942Sscottl			offsetof(struct hpt_iop_request_header, context),
408175942Sscottl			(u_int32_t *)&temp64, 2);
409175942Sscottl		wakeup((void *)((unsigned long)hba->u.itl.mu + index));
410175942Sscottl		break;
411175942Sscottl	}
412175942Sscottl
413175942Sscottl	case IOP_REQUEST_TYPE_SCSI_COMMAND:
414175942Sscottl		bus_space_read_region_4(hba->bar0t, hba->bar0h, index +
415175942Sscottl			offsetof(struct hpt_iop_request_header, context),
416175942Sscottl			(u_int32_t *)&temp64, 2);
417175942Sscottl		srb = (struct hpt_iop_srb *)(unsigned long)temp64;
418175942Sscottl		dxfer = bus_space_read_4(hba->bar0t, hba->bar0h,
419175942Sscottl				index + offsetof(struct hpt_iop_request_scsi_command,
420175942Sscottl				dataxfer_length));
421175942Sscottlsrb_complete:
422175942Sscottl		ccb = (union ccb *)srb->ccb;
423175942Sscottl		if (ccb->ccb_h.flags & CAM_CDB_POINTER)
424175942Sscottl			cdb = ccb->csio.cdb_io.cdb_ptr;
425175942Sscottl		else
426175942Sscottl			cdb = ccb->csio.cdb_io.cdb_bytes;
427175942Sscottl
428175942Sscottl		if (cdb[0] == SYNCHRONIZE_CACHE) { /* ??? */
429175942Sscottl			ccb->ccb_h.status = CAM_REQ_CMP;
430175942Sscottl			goto scsi_done;
431175942Sscottl		}
432175942Sscottl
433175942Sscottl		switch (result) {
434175942Sscottl		case IOP_RESULT_SUCCESS:
435175942Sscottl			switch (ccb->ccb_h.flags & CAM_DIR_MASK) {
436175942Sscottl			case CAM_DIR_IN:
437175942Sscottl				bus_dmamap_sync(hba->io_dmat,
438175942Sscottl					srb->dma_map, BUS_DMASYNC_POSTREAD);
439175942Sscottl				bus_dmamap_unload(hba->io_dmat, srb->dma_map);
440175942Sscottl				break;
441175942Sscottl			case CAM_DIR_OUT:
442175942Sscottl				bus_dmamap_sync(hba->io_dmat,
443175942Sscottl					srb->dma_map, BUS_DMASYNC_POSTWRITE);
444175942Sscottl				bus_dmamap_unload(hba->io_dmat, srb->dma_map);
445175942Sscottl				break;
446175942Sscottl			}
447175942Sscottl
448175942Sscottl			ccb->ccb_h.status = CAM_REQ_CMP;
449175942Sscottl			break;
450175942Sscottl
451175942Sscottl		case IOP_RESULT_BAD_TARGET:
452175942Sscottl			ccb->ccb_h.status = CAM_DEV_NOT_THERE;
453175942Sscottl			break;
454175942Sscottl		case IOP_RESULT_BUSY:
455175942Sscottl			ccb->ccb_h.status = CAM_BUSY;
456175942Sscottl			break;
457175942Sscottl		case IOP_RESULT_INVALID_REQUEST:
458175942Sscottl			ccb->ccb_h.status = CAM_REQ_INVALID;
459175942Sscottl			break;
460175942Sscottl		case IOP_RESULT_FAIL:
461175942Sscottl			ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
462175942Sscottl			break;
463175942Sscottl		case IOP_RESULT_RESET:
464175942Sscottl			ccb->ccb_h.status = CAM_BUSY;
465175942Sscottl			break;
466175942Sscottl		case IOP_RESULT_CHECK_CONDITION:
467226910Smarius			memset(&ccb->csio.sense_data, 0,
468226910Smarius			    sizeof(ccb->csio.sense_data));
469226910Smarius			if (dxfer < ccb->csio.sense_len)
470226910Smarius				ccb->csio.sense_resid = ccb->csio.sense_len -
471226910Smarius				    dxfer;
472226910Smarius			else
473226910Smarius				ccb->csio.sense_resid = 0;
474175942Sscottl			if (srb->srb_flag & HPT_SRB_FLAG_HIGH_MEM_ACESS) {/*iop*/
475175942Sscottl				bus_space_read_region_1(hba->bar0t, hba->bar0h,
476175942Sscottl					index + offsetof(struct hpt_iop_request_scsi_command,
477175942Sscottl					sg_list), (u_int8_t *)&ccb->csio.sense_data,
478175942Sscottl					MIN(dxfer, sizeof(ccb->csio.sense_data)));
479175942Sscottl			} else {
480175942Sscottl				memcpy(&ccb->csio.sense_data, &req->sg_list,
481175942Sscottl					MIN(dxfer, sizeof(ccb->csio.sense_data)));
482175942Sscottl			}
483175942Sscottl			ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
484175942Sscottl			ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
485175942Sscottl			ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
486175942Sscottl			break;
487175942Sscottl		default:
488175942Sscottl			ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
489175942Sscottl			break;
490175942Sscottl		}
491175942Sscottlscsi_done:
492175942Sscottl		if (srb->srb_flag & HPT_SRB_FLAG_HIGH_MEM_ACESS)
493175942Sscottl			BUS_SPACE_WRT4_ITL(outbound_queue, index);
494175942Sscottl
495175942Sscottl		ccb->csio.resid = ccb->csio.dxfer_len - dxfer;
496175942Sscottl
497175942Sscottl		hptiop_free_srb(hba, srb);
498175942Sscottl		xpt_done(ccb);
499175942Sscottl		break;
500175942Sscottl	}
501175942Sscottl}
502175942Sscottl
503175942Sscottlstatic void hptiop_drain_outbound_queue_itl(struct hpt_iop_hba *hba)
504175942Sscottl{
505175942Sscottl	u_int32_t req, temp;
506175942Sscottl
507175942Sscottl	while ((req = BUS_SPACE_RD4_ITL(outbound_queue)) !=IOPMU_QUEUE_EMPTY) {
508175942Sscottl		if (req & IOPMU_QUEUE_MASK_HOST_BITS)
509175942Sscottl			hptiop_request_callback_itl(hba, req);
510175942Sscottl		else {
511175942Sscottl			struct hpt_iop_request_header *p;
512175942Sscottl
513175942Sscottl			p = (struct hpt_iop_request_header *)
514175942Sscottl				((char *)hba->u.itl.mu + req);
515175942Sscottl			temp = bus_space_read_4(hba->bar0t,
516175942Sscottl					hba->bar0h,req +
517175942Sscottl					offsetof(struct hpt_iop_request_header,
518175942Sscottl						flags));
519175942Sscottl			if (temp & IOP_REQUEST_FLAG_SYNC_REQUEST) {
520175942Sscottl				u_int64_t temp64;
521175942Sscottl				bus_space_read_region_4(hba->bar0t,
522175942Sscottl					hba->bar0h,req +
523175942Sscottl					offsetof(struct hpt_iop_request_header,
524175942Sscottl						context),
525175942Sscottl					(u_int32_t *)&temp64, 2);
526175942Sscottl				if (temp64) {
527175942Sscottl					hptiop_request_callback_itl(hba, req);
528175942Sscottl				} else {
529175942Sscottl					temp64 = 1;
530175942Sscottl					bus_space_write_region_4(hba->bar0t,
531175942Sscottl						hba->bar0h,req +
532175942Sscottl						offsetof(struct hpt_iop_request_header,
533175942Sscottl							context),
534175942Sscottl						(u_int32_t *)&temp64, 2);
535175942Sscottl				}
536175942Sscottl			} else
537175942Sscottl				hptiop_request_callback_itl(hba, req);
538175942Sscottl		}
539175942Sscottl	}
540175942Sscottl}
541175942Sscottl
542175942Sscottlstatic int hptiop_intr_itl(struct hpt_iop_hba * hba)
543175942Sscottl{
544169412Sscottl	u_int32_t status;
545169412Sscottl	int ret = 0;
546169412Sscottl
547175942Sscottl	status = BUS_SPACE_RD4_ITL(outbound_intstatus);
548169412Sscottl
549169412Sscottl	if (status & IOPMU_OUTBOUND_INT_MSG0) {
550175942Sscottl		u_int32_t msg = BUS_SPACE_RD4_ITL(outbound_msgaddr0);
551175942Sscottl		KdPrint(("hptiop: received outbound msg %x\n", msg));
552175942Sscottl		BUS_SPACE_WRT4_ITL(outbound_intstatus, IOPMU_OUTBOUND_INT_MSG0);
553175942Sscottl		hptiop_os_message_callback(hba, msg);
554169412Sscottl		ret = 1;
555169412Sscottl	}
556169412Sscottl
557169412Sscottl	if (status & IOPMU_OUTBOUND_INT_POSTQUEUE) {
558175942Sscottl		hptiop_drain_outbound_queue_itl(hba);
559175942Sscottl		ret = 1;
560175942Sscottl	}
561175942Sscottl
562175942Sscottl	return ret;
563175942Sscottl}
564175942Sscottl
565175942Sscottlstatic void hptiop_request_callback_mv(struct hpt_iop_hba * hba,
566175942Sscottl							u_int64_t _tag)
567175942Sscottl{
568175942Sscottl	u_int32_t context = (u_int32_t)_tag;
569175942Sscottl
570175942Sscottl	if (context & MVIOP_CMD_TYPE_SCSI) {
571175942Sscottl		struct hpt_iop_srb *srb;
572175942Sscottl		struct hpt_iop_request_scsi_command *req;
573175942Sscottl		union ccb *ccb;
574175942Sscottl		u_int8_t *cdb;
575175942Sscottl
576175942Sscottl		srb = hba->srb[context >> MVIOP_REQUEST_NUMBER_START_BIT];
577175942Sscottl		req = (struct hpt_iop_request_scsi_command *)srb;
578175942Sscottl		ccb = (union ccb *)srb->ccb;
579175942Sscottl		if (ccb->ccb_h.flags & CAM_CDB_POINTER)
580175942Sscottl			cdb = ccb->csio.cdb_io.cdb_ptr;
581175942Sscottl		else
582175942Sscottl			cdb = ccb->csio.cdb_io.cdb_bytes;
583175942Sscottl
584175942Sscottl		if (cdb[0] == SYNCHRONIZE_CACHE) { /* ??? */
585175942Sscottl			ccb->ccb_h.status = CAM_REQ_CMP;
586175942Sscottl			goto scsi_done;
587175942Sscottl		}
588175942Sscottl		if (context & MVIOP_MU_QUEUE_REQUEST_RESULT_BIT)
589175942Sscottl			req->header.result = IOP_RESULT_SUCCESS;
590175942Sscottl
591175942Sscottl		switch (req->header.result) {
592175942Sscottl		case IOP_RESULT_SUCCESS:
593175942Sscottl			switch (ccb->ccb_h.flags & CAM_DIR_MASK) {
594175942Sscottl			case CAM_DIR_IN:
595175942Sscottl				bus_dmamap_sync(hba->io_dmat,
596175942Sscottl					srb->dma_map, BUS_DMASYNC_POSTREAD);
597175942Sscottl				bus_dmamap_unload(hba->io_dmat, srb->dma_map);
598175942Sscottl				break;
599175942Sscottl			case CAM_DIR_OUT:
600175942Sscottl				bus_dmamap_sync(hba->io_dmat,
601175942Sscottl					srb->dma_map, BUS_DMASYNC_POSTWRITE);
602175942Sscottl				bus_dmamap_unload(hba->io_dmat, srb->dma_map);
603175942Sscottl				break;
604169412Sscottl			}
605175942Sscottl			ccb->ccb_h.status = CAM_REQ_CMP;
606175942Sscottl			break;
607175942Sscottl		case IOP_RESULT_BAD_TARGET:
608175942Sscottl			ccb->ccb_h.status = CAM_DEV_NOT_THERE;
609175942Sscottl			break;
610175942Sscottl		case IOP_RESULT_BUSY:
611175942Sscottl			ccb->ccb_h.status = CAM_BUSY;
612175942Sscottl			break;
613175942Sscottl		case IOP_RESULT_INVALID_REQUEST:
614175942Sscottl			ccb->ccb_h.status = CAM_REQ_INVALID;
615175942Sscottl			break;
616175942Sscottl		case IOP_RESULT_FAIL:
617175942Sscottl			ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
618175942Sscottl			break;
619175942Sscottl		case IOP_RESULT_RESET:
620175942Sscottl			ccb->ccb_h.status = CAM_BUSY;
621175942Sscottl			break;
622175942Sscottl		case IOP_RESULT_CHECK_CONDITION:
623226910Smarius			memset(&ccb->csio.sense_data, 0,
624226910Smarius			    sizeof(ccb->csio.sense_data));
625226910Smarius			if (req->dataxfer_length < ccb->csio.sense_len)
626226910Smarius				ccb->csio.sense_resid = ccb->csio.sense_len -
627226910Smarius				    req->dataxfer_length;
628226910Smarius			else
629226910Smarius				ccb->csio.sense_resid = 0;
630175942Sscottl			memcpy(&ccb->csio.sense_data, &req->sg_list,
631175942Sscottl				MIN(req->dataxfer_length, sizeof(ccb->csio.sense_data)));
632175942Sscottl			ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
633175942Sscottl			ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
634175942Sscottl			ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
635175942Sscottl			break;
636175942Sscottl		default:
637175942Sscottl			ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
638175942Sscottl			break;
639169412Sscottl		}
640175942Sscottlscsi_done:
641175942Sscottl		ccb->csio.resid = ccb->csio.dxfer_len - req->dataxfer_length;
642175942Sscottl
643175942Sscottl		hptiop_free_srb(hba, srb);
644175942Sscottl		xpt_done(ccb);
645175942Sscottl	} else if (context & MVIOP_CMD_TYPE_IOCTL) {
646175942Sscottl		struct hpt_iop_request_ioctl_command *req = hba->ctlcfg_ptr;
647175942Sscottl		if (context & MVIOP_MU_QUEUE_REQUEST_RESULT_BIT)
648175942Sscottl			hba->config_done = 1;
649175942Sscottl		else
650175942Sscottl			hba->config_done = -1;
651175942Sscottl		wakeup(req);
652175942Sscottl	} else if (context &
653175942Sscottl			(MVIOP_CMD_TYPE_SET_CONFIG |
654175942Sscottl				MVIOP_CMD_TYPE_GET_CONFIG))
655175942Sscottl		hba->config_done = 1;
656175942Sscottl	else {
657175942Sscottl		device_printf(hba->pcidev, "wrong callback type\n");
658175942Sscottl	}
659175942Sscottl}
660175942Sscottl
661242214Sdelphijstatic void hptiop_request_callback_mvfrey(struct hpt_iop_hba * hba,
662242214Sdelphij				u_int32_t _tag)
663242214Sdelphij{
664242214Sdelphij	u_int32_t req_type = _tag & 0xf;
665242214Sdelphij
666242214Sdelphij	struct hpt_iop_srb *srb;
667242214Sdelphij	struct hpt_iop_request_scsi_command *req;
668242214Sdelphij	union ccb *ccb;
669242214Sdelphij	u_int8_t *cdb;
670242214Sdelphij
671242214Sdelphij	switch (req_type) {
672242214Sdelphij	case IOP_REQUEST_TYPE_GET_CONFIG:
673242214Sdelphij	case IOP_REQUEST_TYPE_SET_CONFIG:
674242214Sdelphij		hba->config_done = 1;
675242214Sdelphij		break;
676242214Sdelphij
677242214Sdelphij	case IOP_REQUEST_TYPE_SCSI_COMMAND:
678242214Sdelphij		srb = hba->srb[(_tag >> 4) & 0xff];
679242214Sdelphij		req = (struct hpt_iop_request_scsi_command *)srb;
680242214Sdelphij
681242214Sdelphij		ccb = (union ccb *)srb->ccb;
682242214Sdelphij
683242214Sdelphij		untimeout(hptiop_reset_adapter, hba, ccb->ccb_h.timeout_ch);
684242214Sdelphij
685242214Sdelphij		if (ccb->ccb_h.flags & CAM_CDB_POINTER)
686242214Sdelphij			cdb = ccb->csio.cdb_io.cdb_ptr;
687242214Sdelphij		else
688242214Sdelphij			cdb = ccb->csio.cdb_io.cdb_bytes;
689242214Sdelphij
690242214Sdelphij		if (cdb[0] == SYNCHRONIZE_CACHE) { /* ??? */
691242214Sdelphij			ccb->ccb_h.status = CAM_REQ_CMP;
692242214Sdelphij			goto scsi_done;
693242214Sdelphij		}
694242214Sdelphij
695242214Sdelphij		if (_tag & MVFREYIOPMU_QUEUE_REQUEST_RESULT_BIT)
696242214Sdelphij			req->header.result = IOP_RESULT_SUCCESS;
697242214Sdelphij
698242214Sdelphij		switch (req->header.result) {
699242214Sdelphij		case IOP_RESULT_SUCCESS:
700242214Sdelphij			switch (ccb->ccb_h.flags & CAM_DIR_MASK) {
701242214Sdelphij			case CAM_DIR_IN:
702242214Sdelphij				bus_dmamap_sync(hba->io_dmat,
703242214Sdelphij						srb->dma_map, BUS_DMASYNC_POSTREAD);
704242214Sdelphij				bus_dmamap_unload(hba->io_dmat, srb->dma_map);
705242214Sdelphij				break;
706242214Sdelphij			case CAM_DIR_OUT:
707242214Sdelphij				bus_dmamap_sync(hba->io_dmat,
708242214Sdelphij						srb->dma_map, BUS_DMASYNC_POSTWRITE);
709242214Sdelphij				bus_dmamap_unload(hba->io_dmat, srb->dma_map);
710242214Sdelphij				break;
711242214Sdelphij			}
712242214Sdelphij			ccb->ccb_h.status = CAM_REQ_CMP;
713242214Sdelphij			break;
714242214Sdelphij		case IOP_RESULT_BAD_TARGET:
715242214Sdelphij			ccb->ccb_h.status = CAM_DEV_NOT_THERE;
716242214Sdelphij			break;
717242214Sdelphij		case IOP_RESULT_BUSY:
718242214Sdelphij			ccb->ccb_h.status = CAM_BUSY;
719242214Sdelphij			break;
720242214Sdelphij		case IOP_RESULT_INVALID_REQUEST:
721242214Sdelphij			ccb->ccb_h.status = CAM_REQ_INVALID;
722242214Sdelphij			break;
723242214Sdelphij		case IOP_RESULT_FAIL:
724242214Sdelphij			ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
725242214Sdelphij			break;
726242214Sdelphij		case IOP_RESULT_RESET:
727242214Sdelphij			ccb->ccb_h.status = CAM_BUSY;
728242214Sdelphij			break;
729242214Sdelphij		case IOP_RESULT_CHECK_CONDITION:
730242214Sdelphij			memset(&ccb->csio.sense_data, 0,
731242214Sdelphij			       sizeof(ccb->csio.sense_data));
732242214Sdelphij			if (req->dataxfer_length < ccb->csio.sense_len)
733242214Sdelphij				ccb->csio.sense_resid = ccb->csio.sense_len -
734242214Sdelphij				req->dataxfer_length;
735242214Sdelphij			else
736242214Sdelphij				ccb->csio.sense_resid = 0;
737242214Sdelphij			memcpy(&ccb->csio.sense_data, &req->sg_list,
738242214Sdelphij			       MIN(req->dataxfer_length, sizeof(ccb->csio.sense_data)));
739242214Sdelphij			ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
740242214Sdelphij			ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
741242214Sdelphij			ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
742242214Sdelphij			break;
743242214Sdelphij		default:
744242214Sdelphij			ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
745242214Sdelphij			break;
746242214Sdelphij		}
747242214Sdelphijscsi_done:
748242214Sdelphij		ccb->csio.resid = ccb->csio.dxfer_len - req->dataxfer_length;
749242214Sdelphij
750242214Sdelphij		hptiop_free_srb(hba, srb);
751242214Sdelphij		xpt_done(ccb);
752242214Sdelphij		break;
753242214Sdelphij	case IOP_REQUEST_TYPE_IOCTL_COMMAND:
754242214Sdelphij		if (_tag & MVFREYIOPMU_QUEUE_REQUEST_RESULT_BIT)
755242214Sdelphij			hba->config_done = 1;
756242214Sdelphij		else
757242214Sdelphij			hba->config_done = -1;
758242214Sdelphij		wakeup((struct hpt_iop_request_ioctl_command *)hba->ctlcfg_ptr);
759242214Sdelphij		break;
760242214Sdelphij	default:
761242214Sdelphij		device_printf(hba->pcidev, "wrong callback type\n");
762242214Sdelphij		break;
763242214Sdelphij	}
764242214Sdelphij}
765242214Sdelphij
766175942Sscottlstatic void hptiop_drain_outbound_queue_mv(struct hpt_iop_hba * hba)
767175942Sscottl{
768175942Sscottl	u_int64_t req;
769175942Sscottl
770175942Sscottl	while ((req = hptiop_mv_outbound_read(hba))) {
771175942Sscottl		if (req & MVIOP_MU_QUEUE_ADDR_HOST_BIT) {
772175942Sscottl			if (req & MVIOP_MU_QUEUE_REQUEST_RETURN_CONTEXT) {
773175942Sscottl				hptiop_request_callback_mv(hba, req);
774175942Sscottl			}
775175942Sscottl	    	}
776175942Sscottl	}
777175942Sscottl}
778175942Sscottl
779175942Sscottlstatic int hptiop_intr_mv(struct hpt_iop_hba * hba)
780175942Sscottl{
781175942Sscottl	u_int32_t status;
782175942Sscottl	int ret = 0;
783175942Sscottl
784175942Sscottl	status = BUS_SPACE_RD4_MV0(outbound_doorbell);
785175942Sscottl
786175942Sscottl	if (status)
787175942Sscottl		BUS_SPACE_WRT4_MV0(outbound_doorbell, ~status);
788175942Sscottl
789175942Sscottl	if (status & MVIOP_MU_OUTBOUND_INT_MSG) {
790175942Sscottl		u_int32_t msg = BUS_SPACE_RD4_MV2(outbound_msg);
791175942Sscottl		KdPrint(("hptiop: received outbound msg %x\n", msg));
792175942Sscottl		hptiop_os_message_callback(hba, msg);
793169412Sscottl		ret = 1;
794169412Sscottl	}
795175942Sscottl
796175942Sscottl	if (status & MVIOP_MU_OUTBOUND_INT_POSTQUEUE) {
797175942Sscottl		hptiop_drain_outbound_queue_mv(hba);
798175942Sscottl		ret = 1;
799175942Sscottl	}
800175942Sscottl
801169412Sscottl	return ret;
802169412Sscottl}
803169412Sscottl
804242214Sdelphijstatic int hptiop_intr_mvfrey(struct hpt_iop_hba * hba)
805242214Sdelphij{
806242214Sdelphij	u_int32_t status, _tag, cptr;
807242214Sdelphij	int ret = 0;
808242214Sdelphij
809242214Sdelphij	if (hba->initialized) {
810242214Sdelphij		BUS_SPACE_WRT4_MVFREY2(pcie_f0_int_enable, 0);
811242214Sdelphij	}
812242214Sdelphij
813242214Sdelphij	status = BUS_SPACE_RD4_MVFREY2(f0_doorbell);
814242214Sdelphij	if (status) {
815242214Sdelphij		BUS_SPACE_WRT4_MVFREY2(f0_doorbell, status);
816242214Sdelphij		if (status & CPU_TO_F0_DRBL_MSG_A_BIT) {
817242214Sdelphij			u_int32_t msg = BUS_SPACE_RD4_MVFREY2(cpu_to_f0_msg_a);
818242214Sdelphij			hptiop_os_message_callback(hba, msg);
819242214Sdelphij		}
820242214Sdelphij		ret = 1;
821242214Sdelphij	}
822242214Sdelphij
823242214Sdelphij	status = BUS_SPACE_RD4_MVFREY2(isr_cause);
824242214Sdelphij	if (status) {
825242214Sdelphij		BUS_SPACE_WRT4_MVFREY2(isr_cause, status);
826242214Sdelphij		do {
827242214Sdelphij			cptr = *hba->u.mvfrey.outlist_cptr & 0xff;
828242214Sdelphij			while (hba->u.mvfrey.outlist_rptr != cptr) {
829242214Sdelphij				hba->u.mvfrey.outlist_rptr++;
830242214Sdelphij				if (hba->u.mvfrey.outlist_rptr == hba->u.mvfrey.list_count) {
831242214Sdelphij					hba->u.mvfrey.outlist_rptr = 0;
832242214Sdelphij				}
833242214Sdelphij
834242214Sdelphij				_tag = hba->u.mvfrey.outlist[hba->u.mvfrey.outlist_rptr].val;
835242214Sdelphij				hptiop_request_callback_mvfrey(hba, _tag);
836242214Sdelphij				ret = 2;
837242214Sdelphij			}
838242214Sdelphij		} while (cptr != (*hba->u.mvfrey.outlist_cptr & 0xff));
839242214Sdelphij	}
840242214Sdelphij
841242214Sdelphij	if (hba->initialized) {
842242214Sdelphij		BUS_SPACE_WRT4_MVFREY2(pcie_f0_int_enable, 0x1010);
843242214Sdelphij	}
844242214Sdelphij
845242214Sdelphij	return ret;
846242214Sdelphij}
847242214Sdelphij
848175942Sscottlstatic int hptiop_send_sync_request_itl(struct hpt_iop_hba * hba,
849175942Sscottl					u_int32_t req32, u_int32_t millisec)
850169412Sscottl{
851169412Sscottl	u_int32_t i;
852175942Sscottl	u_int64_t temp64;
853169412Sscottl
854175942Sscottl	BUS_SPACE_WRT4_ITL(inbound_queue, req32);
855175942Sscottl	BUS_SPACE_RD4_ITL(outbound_intstatus);
856169412Sscottl
857169412Sscottl	for (i = 0; i < millisec; i++) {
858175942Sscottl		hptiop_intr_itl(hba);
859175942Sscottl		bus_space_read_region_4(hba->bar0t, hba->bar0h, req32 +
860175942Sscottl			offsetof(struct hpt_iop_request_header, context),
861175942Sscottl			(u_int32_t *)&temp64, 2);
862175942Sscottl		if (temp64)
863169412Sscottl			return 0;
864169412Sscottl		DELAY(1000);
865169412Sscottl	}
866169412Sscottl
867169412Sscottl	return -1;
868169412Sscottl}
869169412Sscottl
870175942Sscottlstatic int hptiop_send_sync_request_mv(struct hpt_iop_hba *hba,
871175942Sscottl					void *req, u_int32_t millisec)
872169412Sscottl{
873169412Sscottl	u_int32_t i;
874175942Sscottl	u_int64_t phy_addr;
875175942Sscottl	hba->config_done = 0;
876169412Sscottl
877175942Sscottl	phy_addr = hba->ctlcfgcmd_phy |
878175942Sscottl			(u_int64_t)MVIOP_MU_QUEUE_ADDR_HOST_BIT;
879175942Sscottl	((struct hpt_iop_request_get_config *)req)->header.flags |=
880175942Sscottl		IOP_REQUEST_FLAG_SYNC_REQUEST |
881175942Sscottl		IOP_REQUEST_FLAG_OUTPUT_CONTEXT;
882175942Sscottl	hptiop_mv_inbound_write(phy_addr, hba);
883175942Sscottl	BUS_SPACE_RD4_MV0(outbound_intmask);
884169412Sscottl
885175942Sscottl	for (i = 0; i < millisec; i++) {
886175942Sscottl		hptiop_intr_mv(hba);
887175942Sscottl		if (hba->config_done)
888175942Sscottl			return 0;
889175942Sscottl		DELAY(1000);
890175942Sscottl	}
891175942Sscottl	return -1;
892175942Sscottl}
893169412Sscottl
894242214Sdelphijstatic int hptiop_send_sync_request_mvfrey(struct hpt_iop_hba *hba,
895242214Sdelphij					void *req, u_int32_t millisec)
896242214Sdelphij{
897242214Sdelphij	u_int32_t i, index;
898242214Sdelphij	u_int64_t phy_addr;
899242214Sdelphij	struct hpt_iop_request_header *reqhdr =
900242214Sdelphij										(struct hpt_iop_request_header *)req;
901242214Sdelphij
902242214Sdelphij	hba->config_done = 0;
903242214Sdelphij
904242214Sdelphij	phy_addr = hba->ctlcfgcmd_phy;
905242214Sdelphij	reqhdr->flags = IOP_REQUEST_FLAG_SYNC_REQUEST
906242214Sdelphij					| IOP_REQUEST_FLAG_OUTPUT_CONTEXT
907242214Sdelphij					| IOP_REQUEST_FLAG_ADDR_BITS
908242214Sdelphij					| ((phy_addr >> 16) & 0xffff0000);
909242214Sdelphij	reqhdr->context = ((phy_addr & 0xffffffff) << 32 )
910242214Sdelphij					| IOPMU_QUEUE_ADDR_HOST_BIT | reqhdr->type;
911242214Sdelphij
912242214Sdelphij	hba->u.mvfrey.inlist_wptr++;
913242214Sdelphij	index = hba->u.mvfrey.inlist_wptr & 0x3fff;
914242214Sdelphij
915242214Sdelphij	if (index == hba->u.mvfrey.list_count) {
916242214Sdelphij		index = 0;
917242214Sdelphij		hba->u.mvfrey.inlist_wptr &= ~0x3fff;
918242214Sdelphij		hba->u.mvfrey.inlist_wptr ^= CL_POINTER_TOGGLE;
919242214Sdelphij	}
920242214Sdelphij
921242214Sdelphij	hba->u.mvfrey.inlist[index].addr = phy_addr;
922242214Sdelphij	hba->u.mvfrey.inlist[index].intrfc_len = (reqhdr->size + 3) / 4;
923242214Sdelphij
924242214Sdelphij	BUS_SPACE_WRT4_MVFREY2(inbound_write_ptr, hba->u.mvfrey.inlist_wptr);
925242214Sdelphij	BUS_SPACE_RD4_MVFREY2(inbound_write_ptr);
926242214Sdelphij
927242214Sdelphij	for (i = 0; i < millisec; i++) {
928242214Sdelphij		hptiop_intr_mvfrey(hba);
929242214Sdelphij		if (hba->config_done)
930242214Sdelphij			return 0;
931242214Sdelphij		DELAY(1000);
932242214Sdelphij	}
933242214Sdelphij	return -1;
934242214Sdelphij}
935242214Sdelphij
936175942Sscottlstatic int hptiop_send_sync_msg(struct hpt_iop_hba *hba,
937175942Sscottl					u_int32_t msg, u_int32_t millisec)
938175942Sscottl{
939175942Sscottl	u_int32_t i;
940169412Sscottl
941175942Sscottl	hba->msg_done = 0;
942175942Sscottl	hba->ops->post_msg(hba, msg);
943175942Sscottl
944175942Sscottl	for (i=0; i<millisec; i++) {
945175942Sscottl		hba->ops->iop_intr(hba);
946175942Sscottl		if (hba->msg_done)
947169412Sscottl			break;
948169412Sscottl		DELAY(1000);
949169412Sscottl	}
950169412Sscottl
951175942Sscottl	return hba->msg_done? 0 : -1;
952169412Sscottl}
953169412Sscottl
954175942Sscottlstatic int hptiop_get_config_itl(struct hpt_iop_hba * hba,
955175942Sscottl				struct hpt_iop_request_get_config * config)
956169412Sscottl{
957175942Sscottl	u_int32_t req32;
958169412Sscottl
959175942Sscottl	config->header.size = sizeof(struct hpt_iop_request_get_config);
960175942Sscottl	config->header.type = IOP_REQUEST_TYPE_GET_CONFIG;
961175942Sscottl	config->header.flags = IOP_REQUEST_FLAG_SYNC_REQUEST;
962175942Sscottl	config->header.result = IOP_RESULT_PENDING;
963175942Sscottl	config->header.context = 0;
964175942Sscottl
965175942Sscottl	req32 = BUS_SPACE_RD4_ITL(inbound_queue);
966175942Sscottl	if (req32 == IOPMU_QUEUE_EMPTY)
967169412Sscottl		return -1;
968169412Sscottl
969175942Sscottl	bus_space_write_region_4(hba->bar0t, hba->bar0h,
970175942Sscottl			req32, (u_int32_t *)config,
971175942Sscottl			sizeof(struct hpt_iop_request_header) >> 2);
972175942Sscottl
973175942Sscottl	if (hptiop_send_sync_request_itl(hba, req32, 20000)) {
974175942Sscottl		KdPrint(("hptiop: get config send cmd failed"));
975175942Sscottl		return -1;
976175942Sscottl	}
977175942Sscottl
978175942Sscottl	bus_space_read_region_4(hba->bar0t, hba->bar0h,
979175942Sscottl			req32, (u_int32_t *)config,
980175942Sscottl			sizeof(struct hpt_iop_request_get_config) >> 2);
981175942Sscottl
982175942Sscottl	BUS_SPACE_WRT4_ITL(outbound_queue, req32);
983175942Sscottl
984175942Sscottl	return 0;
985175942Sscottl}
986175942Sscottl
987175942Sscottlstatic int hptiop_get_config_mv(struct hpt_iop_hba * hba,
988175942Sscottl				struct hpt_iop_request_get_config * config)
989175942Sscottl{
990175942Sscottl	struct hpt_iop_request_get_config *req;
991175942Sscottl
992175942Sscottl	if (!(req = hba->ctlcfg_ptr))
993175942Sscottl		return -1;
994175942Sscottl
995169412Sscottl	req->header.flags = 0;
996169412Sscottl	req->header.type = IOP_REQUEST_TYPE_GET_CONFIG;
997169412Sscottl	req->header.size = sizeof(struct hpt_iop_request_get_config);
998169412Sscottl	req->header.result = IOP_RESULT_PENDING;
999175942Sscottl	req->header.context = MVIOP_CMD_TYPE_GET_CONFIG;
1000169412Sscottl
1001175942Sscottl	if (hptiop_send_sync_request_mv(hba, req, 20000)) {
1002175942Sscottl		KdPrint(("hptiop: get config send cmd failed"));
1003169412Sscottl		return -1;
1004169412Sscottl	}
1005169412Sscottl
1006169412Sscottl	*config = *req;
1007169412Sscottl	return 0;
1008169412Sscottl}
1009169412Sscottl
1010242214Sdelphijstatic int hptiop_get_config_mvfrey(struct hpt_iop_hba * hba,
1011242214Sdelphij				struct hpt_iop_request_get_config * config)
1012242214Sdelphij{
1013242214Sdelphij	struct hpt_iop_request_get_config *info = hba->u.mvfrey.config;
1014242214Sdelphij
1015242214Sdelphij	if (info->header.size != sizeof(struct hpt_iop_request_get_config) ||
1016242214Sdelphij	    info->header.type != IOP_REQUEST_TYPE_GET_CONFIG) {
1017242214Sdelphij		KdPrint(("hptiop: header size %x/%x type %x/%x",
1018242214Sdelphij			 info->header.size, (int)sizeof(struct hpt_iop_request_get_config),
1019242214Sdelphij			 info->header.type, IOP_REQUEST_TYPE_GET_CONFIG));
1020242214Sdelphij		return -1;
1021242214Sdelphij	}
1022242214Sdelphij
1023242214Sdelphij	config->interface_version = info->interface_version;
1024242214Sdelphij	config->firmware_version = info->firmware_version;
1025242214Sdelphij	config->max_requests = info->max_requests;
1026242214Sdelphij	config->request_size = info->request_size;
1027242214Sdelphij	config->max_sg_count = info->max_sg_count;
1028242214Sdelphij	config->data_transfer_length = info->data_transfer_length;
1029242214Sdelphij	config->alignment_mask = info->alignment_mask;
1030242214Sdelphij	config->max_devices = info->max_devices;
1031242214Sdelphij	config->sdram_size = info->sdram_size;
1032242214Sdelphij
1033242214Sdelphij	KdPrint(("hptiop: maxreq %x reqsz %x datalen %x maxdev %x sdram %x",
1034242214Sdelphij		 config->max_requests, config->request_size,
1035242214Sdelphij		 config->data_transfer_length, config->max_devices,
1036242214Sdelphij		 config->sdram_size));
1037242214Sdelphij
1038242214Sdelphij	return 0;
1039242214Sdelphij}
1040242214Sdelphij
1041175942Sscottlstatic int hptiop_set_config_itl(struct hpt_iop_hba *hba,
1042175942Sscottl				struct hpt_iop_request_set_config *config)
1043169412Sscottl{
1044169412Sscottl	u_int32_t req32;
1045169412Sscottl
1046175942Sscottl	req32 = BUS_SPACE_RD4_ITL(inbound_queue);
1047175942Sscottl
1048169412Sscottl	if (req32 == IOPMU_QUEUE_EMPTY)
1049169412Sscottl		return -1;
1050169412Sscottl
1051175942Sscottl	config->header.size = sizeof(struct hpt_iop_request_set_config);
1052175942Sscottl	config->header.type = IOP_REQUEST_TYPE_SET_CONFIG;
1053175942Sscottl	config->header.flags = IOP_REQUEST_FLAG_SYNC_REQUEST;
1054175942Sscottl	config->header.result = IOP_RESULT_PENDING;
1055175942Sscottl	config->header.context = 0;
1056175942Sscottl
1057175942Sscottl	bus_space_write_region_4(hba->bar0t, hba->bar0h, req32,
1058175942Sscottl		(u_int32_t *)config,
1059175942Sscottl		sizeof(struct hpt_iop_request_set_config) >> 2);
1060175942Sscottl
1061175942Sscottl	if (hptiop_send_sync_request_itl(hba, req32, 20000)) {
1062175942Sscottl		KdPrint(("hptiop: set config send cmd failed"));
1063175942Sscottl		return -1;
1064175942Sscottl	}
1065175942Sscottl
1066175942Sscottl	BUS_SPACE_WRT4_ITL(outbound_queue, req32);
1067175942Sscottl
1068175942Sscottl	return 0;
1069175942Sscottl}
1070175942Sscottl
1071175942Sscottlstatic int hptiop_set_config_mv(struct hpt_iop_hba *hba,
1072175942Sscottl				struct hpt_iop_request_set_config *config)
1073175942Sscottl{
1074175942Sscottl	struct hpt_iop_request_set_config *req;
1075175942Sscottl
1076175942Sscottl	if (!(req = hba->ctlcfg_ptr))
1077175942Sscottl		return -1;
1078175942Sscottl
1079169412Sscottl	memcpy((u_int8_t *)req + sizeof(struct hpt_iop_request_header),
1080169412Sscottl		(u_int8_t *)config + sizeof(struct hpt_iop_request_header),
1081175942Sscottl		sizeof(struct hpt_iop_request_set_config) -
1082175942Sscottl			sizeof(struct hpt_iop_request_header));
1083175942Sscottl
1084169412Sscottl	req->header.flags = 0;
1085169412Sscottl	req->header.type = IOP_REQUEST_TYPE_SET_CONFIG;
1086169412Sscottl	req->header.size = sizeof(struct hpt_iop_request_set_config);
1087169412Sscottl	req->header.result = IOP_RESULT_PENDING;
1088175942Sscottl	req->header.context = MVIOP_CMD_TYPE_SET_CONFIG;
1089169412Sscottl
1090175942Sscottl	if (hptiop_send_sync_request_mv(hba, req, 20000)) {
1091175942Sscottl		KdPrint(("hptiop: set config send cmd failed"));
1092169412Sscottl		return -1;
1093169412Sscottl	}
1094169412Sscottl
1095169412Sscottl	return 0;
1096169412Sscottl}
1097169412Sscottl
1098242214Sdelphijstatic int hptiop_set_config_mvfrey(struct hpt_iop_hba *hba,
1099242214Sdelphij				struct hpt_iop_request_set_config *config)
1100242214Sdelphij{
1101242214Sdelphij	struct hpt_iop_request_set_config *req;
1102242214Sdelphij
1103242214Sdelphij	if (!(req = hba->ctlcfg_ptr))
1104242214Sdelphij		return -1;
1105242214Sdelphij
1106242214Sdelphij	memcpy((u_int8_t *)req + sizeof(struct hpt_iop_request_header),
1107242214Sdelphij		(u_int8_t *)config + sizeof(struct hpt_iop_request_header),
1108242214Sdelphij		sizeof(struct hpt_iop_request_set_config) -
1109242214Sdelphij			sizeof(struct hpt_iop_request_header));
1110242214Sdelphij
1111242214Sdelphij	req->header.type = IOP_REQUEST_TYPE_SET_CONFIG;
1112242214Sdelphij	req->header.size = sizeof(struct hpt_iop_request_set_config);
1113242214Sdelphij	req->header.result = IOP_RESULT_PENDING;
1114242214Sdelphij
1115242214Sdelphij	if (hptiop_send_sync_request_mvfrey(hba, req, 20000)) {
1116242214Sdelphij		KdPrint(("hptiop: set config send cmd failed"));
1117242214Sdelphij		return -1;
1118242214Sdelphij	}
1119242214Sdelphij
1120242214Sdelphij	return 0;
1121242214Sdelphij}
1122242214Sdelphij
1123175942Sscottlstatic int hptiop_post_ioctl_command_itl(struct hpt_iop_hba *hba,
1124175942Sscottl				u_int32_t req32,
1125175942Sscottl				struct hpt_iop_ioctl_param *pParams)
1126169412Sscottl{
1127175942Sscottl	u_int64_t temp64;
1128175942Sscottl	struct hpt_iop_request_ioctl_command req;
1129169412Sscottl
1130175942Sscottl	if ((((pParams->nInBufferSize + 3) & ~3) + pParams->nOutBufferSize) >
1131175942Sscottl			(hba->max_request_size -
1132175942Sscottl			offsetof(struct hpt_iop_request_ioctl_command, buf))) {
1133175942Sscottl		device_printf(hba->pcidev, "request size beyond max value");
1134175942Sscottl		return -1;
1135175942Sscottl	}
1136175942Sscottl
1137175942Sscottl	req.header.size = offsetof(struct hpt_iop_request_ioctl_command, buf)
1138175942Sscottl		+ pParams->nInBufferSize;
1139175942Sscottl	req.header.type = IOP_REQUEST_TYPE_IOCTL_COMMAND;
1140175942Sscottl	req.header.flags = IOP_REQUEST_FLAG_SYNC_REQUEST;
1141175942Sscottl	req.header.result = IOP_RESULT_PENDING;
1142175942Sscottl	req.header.context = req32 + (u_int64_t)(unsigned long)hba->u.itl.mu;
1143175942Sscottl	req.ioctl_code = HPT_CTL_CODE_BSD_TO_IOP(pParams->dwIoControlCode);
1144175942Sscottl	req.inbuf_size = pParams->nInBufferSize;
1145175942Sscottl	req.outbuf_size = pParams->nOutBufferSize;
1146175942Sscottl	req.bytes_returned = 0;
1147175942Sscottl
1148175942Sscottl	bus_space_write_region_4(hba->bar0t, hba->bar0h, req32, (u_int32_t *)&req,
1149175942Sscottl		offsetof(struct hpt_iop_request_ioctl_command, buf)>>2);
1150175942Sscottl
1151175942Sscottl	hptiop_lock_adapter(hba);
1152175942Sscottl
1153175942Sscottl	BUS_SPACE_WRT4_ITL(inbound_queue, req32);
1154175942Sscottl	BUS_SPACE_RD4_ITL(outbound_intstatus);
1155175942Sscottl
1156175942Sscottl	bus_space_read_region_4(hba->bar0t, hba->bar0h, req32 +
1157175942Sscottl		offsetof(struct hpt_iop_request_ioctl_command, header.context),
1158175942Sscottl		(u_int32_t *)&temp64, 2);
1159175942Sscottl	while (temp64) {
1160175942Sscottl		if (hptiop_sleep(hba, (void *)((unsigned long)hba->u.itl.mu + req32),
1161175942Sscottl				PPAUSE, "hptctl", HPT_OSM_TIMEOUT)==0)
1162175942Sscottl			break;
1163175942Sscottl		hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_RESET, 60000);
1164175942Sscottl		bus_space_read_region_4(hba->bar0t, hba->bar0h,req32 +
1165175942Sscottl			offsetof(struct hpt_iop_request_ioctl_command,
1166175942Sscottl				header.context),
1167175942Sscottl			(u_int32_t *)&temp64, 2);
1168175942Sscottl	}
1169175942Sscottl
1170175942Sscottl	hptiop_unlock_adapter(hba);
1171175942Sscottl	return 0;
1172175942Sscottl}
1173175942Sscottl
1174242214Sdelphijstatic int hptiop_bus_space_copyin(struct hpt_iop_hba *hba, u_int32_t bus,
1175242214Sdelphij									void *user, int size)
1176175942Sscottl{
1177175942Sscottl	unsigned char byte;
1178175942Sscottl	int i;
1179175942Sscottl
1180175942Sscottl	for (i=0; i<size; i++) {
1181175942Sscottl		if (copyin((u_int8_t *)user + i, &byte, 1))
1182175942Sscottl			return -1;
1183175942Sscottl		bus_space_write_1(hba->bar0t, hba->bar0h, bus + i, byte);
1184175942Sscottl	}
1185175942Sscottl
1186175942Sscottl	return 0;
1187175942Sscottl}
1188175942Sscottl
1189242214Sdelphijstatic int hptiop_bus_space_copyout(struct hpt_iop_hba *hba, u_int32_t bus,
1190242214Sdelphij									void *user, int size)
1191175942Sscottl{
1192175942Sscottl	unsigned char byte;
1193175942Sscottl	int i;
1194175942Sscottl
1195175942Sscottl	for (i=0; i<size; i++) {
1196175942Sscottl		byte = bus_space_read_1(hba->bar0t, hba->bar0h, bus + i);
1197175942Sscottl		if (copyout(&byte, (u_int8_t *)user + i, 1))
1198175942Sscottl			return -1;
1199175942Sscottl	}
1200175942Sscottl
1201175942Sscottl	return 0;
1202175942Sscottl}
1203175942Sscottl
1204175942Sscottlstatic int hptiop_do_ioctl_itl(struct hpt_iop_hba *hba,
1205175942Sscottl				struct hpt_iop_ioctl_param * pParams)
1206175942Sscottl{
1207175942Sscottl	u_int32_t req32;
1208175942Sscottl	u_int32_t result;
1209175942Sscottl
1210169412Sscottl	if ((pParams->Magic != HPT_IOCTL_MAGIC) &&
1211169412Sscottl		(pParams->Magic != HPT_IOCTL_MAGIC32))
1212169412Sscottl		return EFAULT;
1213175942Sscottl
1214175942Sscottl	req32 = BUS_SPACE_RD4_ITL(inbound_queue);
1215175942Sscottl	if (req32 == IOPMU_QUEUE_EMPTY)
1216169412Sscottl		return EFAULT;
1217169412Sscottl
1218169412Sscottl	if (pParams->nInBufferSize)
1219175942Sscottl		if (hptiop_bus_space_copyin(hba, req32 +
1220175942Sscottl			offsetof(struct hpt_iop_request_ioctl_command, buf),
1221175942Sscottl			(void *)pParams->lpInBuffer, pParams->nInBufferSize))
1222169412Sscottl			goto invalid;
1223169412Sscottl
1224175942Sscottl	if (hptiop_post_ioctl_command_itl(hba, req32, pParams))
1225169412Sscottl		goto invalid;
1226169412Sscottl
1227175942Sscottl	result = bus_space_read_4(hba->bar0t, hba->bar0h, req32 +
1228175942Sscottl			offsetof(struct hpt_iop_request_ioctl_command,
1229175942Sscottl				header.result));
1230175942Sscottl
1231175942Sscottl	if (result == IOP_RESULT_SUCCESS) {
1232169412Sscottl		if (pParams->nOutBufferSize)
1233175942Sscottl			if (hptiop_bus_space_copyout(hba, req32 +
1234175942Sscottl				offsetof(struct hpt_iop_request_ioctl_command, buf) +
1235169412Sscottl					((pParams->nInBufferSize + 3) & ~3),
1236175942Sscottl				(void *)pParams->lpOutBuffer, pParams->nOutBufferSize))
1237169412Sscottl				goto invalid;
1238169412Sscottl
1239175942Sscottl		if (pParams->lpBytesReturned) {
1240175942Sscottl			if (hptiop_bus_space_copyout(hba, req32 +
1241175942Sscottl				offsetof(struct hpt_iop_request_ioctl_command, bytes_returned),
1242175942Sscottl				(void *)pParams->lpBytesReturned, sizeof(unsigned  long)))
1243169412Sscottl				goto invalid;
1244175942Sscottl		}
1245175942Sscottl
1246175942Sscottl		BUS_SPACE_WRT4_ITL(outbound_queue, req32);
1247175942Sscottl
1248169412Sscottl		return 0;
1249169412Sscottl	} else{
1250169412Sscottlinvalid:
1251175942Sscottl		BUS_SPACE_WRT4_ITL(outbound_queue, req32);
1252175942Sscottl
1253169412Sscottl		return EFAULT;
1254169412Sscottl	}
1255169412Sscottl}
1256169412Sscottl
1257175942Sscottlstatic int hptiop_post_ioctl_command_mv(struct hpt_iop_hba *hba,
1258175942Sscottl				struct hpt_iop_request_ioctl_command *req,
1259175942Sscottl				struct hpt_iop_ioctl_param *pParams)
1260169412Sscottl{
1261175942Sscottl	u_int64_t req_phy;
1262175942Sscottl	int size = 0;
1263175942Sscottl
1264175942Sscottl	if ((((pParams->nInBufferSize + 3) & ~3) + pParams->nOutBufferSize) >
1265175942Sscottl			(hba->max_request_size -
1266175942Sscottl			offsetof(struct hpt_iop_request_ioctl_command, buf))) {
1267175942Sscottl		device_printf(hba->pcidev, "request size beyond max value");
1268169412Sscottl		return -1;
1269169412Sscottl	}
1270169412Sscottl
1271169412Sscottl	req->ioctl_code = HPT_CTL_CODE_BSD_TO_IOP(pParams->dwIoControlCode);
1272169412Sscottl	req->inbuf_size = pParams->nInBufferSize;
1273169412Sscottl	req->outbuf_size = pParams->nOutBufferSize;
1274175942Sscottl	req->header.size = offsetof(struct hpt_iop_request_ioctl_command, buf)
1275175942Sscottl					+ pParams->nInBufferSize;
1276175942Sscottl	req->header.context = (u_int64_t)MVIOP_CMD_TYPE_IOCTL;
1277169412Sscottl	req->header.type = IOP_REQUEST_TYPE_IOCTL_COMMAND;
1278169412Sscottl	req->header.result = IOP_RESULT_PENDING;
1279175942Sscottl	req->header.flags = IOP_REQUEST_FLAG_OUTPUT_CONTEXT;
1280175942Sscottl	size = req->header.size >> 8;
1281175942Sscottl	size = size > 3 ? 3 : size;
1282175942Sscottl	req_phy = hba->ctlcfgcmd_phy | MVIOP_MU_QUEUE_ADDR_HOST_BIT | size;
1283175942Sscottl	hptiop_mv_inbound_write(req_phy, hba);
1284169412Sscottl
1285175942Sscottl	BUS_SPACE_RD4_MV0(outbound_intmask);
1286169412Sscottl
1287175942Sscottl	while (hba->config_done == 0) {
1288175942Sscottl		if (hptiop_sleep(hba, req, PPAUSE,
1289175942Sscottl			"hptctl", HPT_OSM_TIMEOUT)==0)
1290175942Sscottl			continue;
1291175942Sscottl		hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_RESET, 60000);
1292169412Sscottl	}
1293169412Sscottl	return 0;
1294169412Sscottl}
1295169412Sscottl
1296175942Sscottlstatic int hptiop_do_ioctl_mv(struct hpt_iop_hba *hba,
1297175942Sscottl				struct hpt_iop_ioctl_param *pParams)
1298175942Sscottl{
1299175942Sscottl	struct hpt_iop_request_ioctl_command *req;
1300175942Sscottl
1301175942Sscottl	if ((pParams->Magic != HPT_IOCTL_MAGIC) &&
1302175942Sscottl		(pParams->Magic != HPT_IOCTL_MAGIC32))
1303175942Sscottl		return EFAULT;
1304175942Sscottl
1305175942Sscottl	req = (struct hpt_iop_request_ioctl_command *)(hba->ctlcfg_ptr);
1306175942Sscottl	hba->config_done = 0;
1307175942Sscottl	hptiop_lock_adapter(hba);
1308175942Sscottl	if (pParams->nInBufferSize)
1309175942Sscottl		if (copyin((void *)pParams->lpInBuffer,
1310175942Sscottl				req->buf, pParams->nInBufferSize))
1311175942Sscottl			goto invalid;
1312175942Sscottl	if (hptiop_post_ioctl_command_mv(hba, req, pParams))
1313175942Sscottl		goto invalid;
1314175942Sscottl
1315175942Sscottl	if (hba->config_done == 1) {
1316175942Sscottl		if (pParams->nOutBufferSize)
1317175942Sscottl			if (copyout(req->buf +
1318175942Sscottl				((pParams->nInBufferSize + 3) & ~3),
1319175942Sscottl				(void *)pParams->lpOutBuffer,
1320175942Sscottl				pParams->nOutBufferSize))
1321175942Sscottl				goto invalid;
1322175942Sscottl
1323175942Sscottl		if (pParams->lpBytesReturned)
1324175942Sscottl			if (copyout(&req->bytes_returned,
1325175942Sscottl				(void*)pParams->lpBytesReturned,
1326175942Sscottl				sizeof(u_int32_t)))
1327175942Sscottl				goto invalid;
1328175942Sscottl		hptiop_unlock_adapter(hba);
1329175942Sscottl		return 0;
1330175942Sscottl	} else{
1331175942Sscottlinvalid:
1332175942Sscottl		hptiop_unlock_adapter(hba);
1333175942Sscottl		return EFAULT;
1334175942Sscottl	}
1335175942Sscottl}
1336175942Sscottl
1337242214Sdelphijstatic int hptiop_post_ioctl_command_mvfrey(struct hpt_iop_hba *hba,
1338242214Sdelphij				struct hpt_iop_request_ioctl_command *req,
1339242214Sdelphij				struct hpt_iop_ioctl_param *pParams)
1340242214Sdelphij{
1341242214Sdelphij	u_int64_t phy_addr;
1342242214Sdelphij	u_int32_t index;
1343242214Sdelphij
1344242214Sdelphij	phy_addr = hba->ctlcfgcmd_phy;
1345242214Sdelphij
1346242214Sdelphij	if ((((pParams->nInBufferSize + 3) & ~3) + pParams->nOutBufferSize) >
1347242214Sdelphij			(hba->max_request_size -
1348242214Sdelphij			offsetof(struct hpt_iop_request_ioctl_command, buf))) {
1349242214Sdelphij		device_printf(hba->pcidev, "request size beyond max value");
1350242214Sdelphij		return -1;
1351242214Sdelphij	}
1352242214Sdelphij
1353242214Sdelphij	req->ioctl_code = HPT_CTL_CODE_BSD_TO_IOP(pParams->dwIoControlCode);
1354242214Sdelphij	req->inbuf_size = pParams->nInBufferSize;
1355242214Sdelphij	req->outbuf_size = pParams->nOutBufferSize;
1356242214Sdelphij	req->header.size = offsetof(struct hpt_iop_request_ioctl_command, buf)
1357242214Sdelphij					+ pParams->nInBufferSize;
1358242214Sdelphij
1359242214Sdelphij	req->header.type = IOP_REQUEST_TYPE_IOCTL_COMMAND;
1360242214Sdelphij	req->header.result = IOP_RESULT_PENDING;
1361242214Sdelphij
1362242214Sdelphij	req->header.flags = IOP_REQUEST_FLAG_SYNC_REQUEST
1363242214Sdelphij						| IOP_REQUEST_FLAG_OUTPUT_CONTEXT
1364242214Sdelphij						| IOP_REQUEST_FLAG_ADDR_BITS
1365242214Sdelphij						| ((phy_addr >> 16) & 0xffff0000);
1366242214Sdelphij	req->header.context = ((phy_addr & 0xffffffff) << 32 )
1367242214Sdelphij						| IOPMU_QUEUE_ADDR_HOST_BIT | req->header.type;
1368242214Sdelphij
1369242214Sdelphij	hba->u.mvfrey.inlist_wptr++;
1370242214Sdelphij	index = hba->u.mvfrey.inlist_wptr & 0x3fff;
1371242214Sdelphij
1372242214Sdelphij	if (index == hba->u.mvfrey.list_count) {
1373242214Sdelphij		index = 0;
1374242214Sdelphij		hba->u.mvfrey.inlist_wptr &= ~0x3fff;
1375242214Sdelphij		hba->u.mvfrey.inlist_wptr ^= CL_POINTER_TOGGLE;
1376242214Sdelphij	}
1377242214Sdelphij
1378242214Sdelphij	hba->u.mvfrey.inlist[index].addr = phy_addr;
1379242214Sdelphij	hba->u.mvfrey.inlist[index].intrfc_len = (req->header.size + 3) / 4;
1380242214Sdelphij
1381242214Sdelphij	BUS_SPACE_WRT4_MVFREY2(inbound_write_ptr, hba->u.mvfrey.inlist_wptr);
1382242214Sdelphij	BUS_SPACE_RD4_MVFREY2(inbound_write_ptr);
1383242214Sdelphij
1384242214Sdelphij	while (hba->config_done == 0) {
1385242214Sdelphij		if (hptiop_sleep(hba, req, PPAUSE,
1386242214Sdelphij			"hptctl", HPT_OSM_TIMEOUT)==0)
1387242214Sdelphij			continue;
1388242214Sdelphij		hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_RESET, 60000);
1389242214Sdelphij	}
1390242214Sdelphij	return 0;
1391242214Sdelphij}
1392242214Sdelphij
1393242214Sdelphijstatic int hptiop_do_ioctl_mvfrey(struct hpt_iop_hba *hba,
1394242214Sdelphij				struct hpt_iop_ioctl_param *pParams)
1395242214Sdelphij{
1396242214Sdelphij	struct hpt_iop_request_ioctl_command *req;
1397242214Sdelphij
1398242214Sdelphij	if ((pParams->Magic != HPT_IOCTL_MAGIC) &&
1399242214Sdelphij		(pParams->Magic != HPT_IOCTL_MAGIC32))
1400242214Sdelphij		return EFAULT;
1401242214Sdelphij
1402242214Sdelphij	req = (struct hpt_iop_request_ioctl_command *)(hba->ctlcfg_ptr);
1403242214Sdelphij	hba->config_done = 0;
1404242214Sdelphij	hptiop_lock_adapter(hba);
1405242214Sdelphij	if (pParams->nInBufferSize)
1406242214Sdelphij		if (copyin((void *)pParams->lpInBuffer,
1407242214Sdelphij				req->buf, pParams->nInBufferSize))
1408242214Sdelphij			goto invalid;
1409242214Sdelphij	if (hptiop_post_ioctl_command_mvfrey(hba, req, pParams))
1410242214Sdelphij		goto invalid;
1411242214Sdelphij
1412242214Sdelphij	if (hba->config_done == 1) {
1413242214Sdelphij		if (pParams->nOutBufferSize)
1414242214Sdelphij			if (copyout(req->buf +
1415242214Sdelphij				((pParams->nInBufferSize + 3) & ~3),
1416242214Sdelphij				(void *)pParams->lpOutBuffer,
1417242214Sdelphij				pParams->nOutBufferSize))
1418242214Sdelphij				goto invalid;
1419242214Sdelphij
1420242214Sdelphij		if (pParams->lpBytesReturned)
1421242214Sdelphij			if (copyout(&req->bytes_returned,
1422242214Sdelphij				(void*)pParams->lpBytesReturned,
1423242214Sdelphij				sizeof(u_int32_t)))
1424242214Sdelphij				goto invalid;
1425242214Sdelphij		hptiop_unlock_adapter(hba);
1426242214Sdelphij		return 0;
1427242214Sdelphij	} else{
1428242214Sdelphijinvalid:
1429242214Sdelphij		hptiop_unlock_adapter(hba);
1430242214Sdelphij		return EFAULT;
1431242214Sdelphij	}
1432242214Sdelphij}
1433242214Sdelphij
1434169412Sscottlstatic int  hptiop_rescan_bus(struct hpt_iop_hba * hba)
1435169412Sscottl{
1436169412Sscottl	union ccb           *ccb;
1437203108Smav
1438203108Smav	if ((ccb = xpt_alloc_ccb()) == NULL)
1439203108Smav		return(ENOMEM);
1440253037Smav	if (xpt_create_path(&ccb->ccb_h.path, NULL, cam_sim_path(hba->sim),
1441203108Smav		CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
1442203108Smav		xpt_free_ccb(ccb);
1443169412Sscottl		return(EIO);
1444203108Smav	}
1445203108Smav	xpt_rescan(ccb);
1446169412Sscottl	return(0);
1447169412Sscottl}
1448169412Sscottl
1449169412Sscottlstatic  bus_dmamap_callback_t   hptiop_map_srb;
1450169412Sscottlstatic  bus_dmamap_callback_t   hptiop_post_scsi_command;
1451175942Sscottlstatic  bus_dmamap_callback_t   hptiop_mv_map_ctlcfg;
1452242214Sdelphijstatic	bus_dmamap_callback_t	hptiop_mvfrey_map_ctlcfg;
1453169412Sscottl
1454175942Sscottlstatic int hptiop_alloc_pci_res_itl(struct hpt_iop_hba *hba)
1455175942Sscottl{
1456175942Sscottl	hba->bar0_rid = 0x10;
1457175942Sscottl	hba->bar0_res = bus_alloc_resource_any(hba->pcidev,
1458175942Sscottl			SYS_RES_MEMORY, &hba->bar0_rid, RF_ACTIVE);
1459175942Sscottl
1460175942Sscottl	if (hba->bar0_res == NULL) {
1461175942Sscottl		device_printf(hba->pcidev,
1462175942Sscottl			"failed to get iop base adrress.\n");
1463175942Sscottl		return -1;
1464175942Sscottl	}
1465175942Sscottl	hba->bar0t = rman_get_bustag(hba->bar0_res);
1466175942Sscottl	hba->bar0h = rman_get_bushandle(hba->bar0_res);
1467175942Sscottl	hba->u.itl.mu = (struct hpt_iopmu_itl *)
1468175942Sscottl				rman_get_virtual(hba->bar0_res);
1469175942Sscottl
1470175942Sscottl	if (!hba->u.itl.mu) {
1471175942Sscottl		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1472175942Sscottl					hba->bar0_rid, hba->bar0_res);
1473175942Sscottl		device_printf(hba->pcidev, "alloc mem res failed\n");
1474175942Sscottl		return -1;
1475175942Sscottl	}
1476175942Sscottl
1477175942Sscottl	return 0;
1478175942Sscottl}
1479175942Sscottl
1480175942Sscottlstatic int hptiop_alloc_pci_res_mv(struct hpt_iop_hba *hba)
1481175942Sscottl{
1482175942Sscottl	hba->bar0_rid = 0x10;
1483175942Sscottl	hba->bar0_res = bus_alloc_resource_any(hba->pcidev,
1484175942Sscottl			SYS_RES_MEMORY, &hba->bar0_rid, RF_ACTIVE);
1485175942Sscottl
1486175942Sscottl	if (hba->bar0_res == NULL) {
1487175942Sscottl		device_printf(hba->pcidev, "failed to get iop bar0.\n");
1488175942Sscottl		return -1;
1489175942Sscottl	}
1490175942Sscottl	hba->bar0t = rman_get_bustag(hba->bar0_res);
1491175942Sscottl	hba->bar0h = rman_get_bushandle(hba->bar0_res);
1492175942Sscottl	hba->u.mv.regs = (struct hpt_iopmv_regs *)
1493175942Sscottl				rman_get_virtual(hba->bar0_res);
1494175942Sscottl
1495175942Sscottl	if (!hba->u.mv.regs) {
1496175942Sscottl		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1497175942Sscottl					hba->bar0_rid, hba->bar0_res);
1498175942Sscottl		device_printf(hba->pcidev, "alloc bar0 mem res failed\n");
1499175942Sscottl		return -1;
1500175942Sscottl	}
1501175942Sscottl
1502175942Sscottl	hba->bar2_rid = 0x18;
1503175942Sscottl	hba->bar2_res = bus_alloc_resource_any(hba->pcidev,
1504175942Sscottl			SYS_RES_MEMORY, &hba->bar2_rid, RF_ACTIVE);
1505175942Sscottl
1506175942Sscottl	if (hba->bar2_res == NULL) {
1507175942Sscottl		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1508175942Sscottl					hba->bar0_rid, hba->bar0_res);
1509175942Sscottl		device_printf(hba->pcidev, "failed to get iop bar2.\n");
1510175942Sscottl		return -1;
1511175942Sscottl	}
1512175942Sscottl
1513175942Sscottl	hba->bar2t = rman_get_bustag(hba->bar2_res);
1514175942Sscottl	hba->bar2h = rman_get_bushandle(hba->bar2_res);
1515175942Sscottl	hba->u.mv.mu = (struct hpt_iopmu_mv *)rman_get_virtual(hba->bar2_res);
1516175942Sscottl
1517175942Sscottl	if (!hba->u.mv.mu) {
1518175942Sscottl		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1519175942Sscottl					hba->bar0_rid, hba->bar0_res);
1520175942Sscottl		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1521175942Sscottl					hba->bar2_rid, hba->bar2_res);
1522175942Sscottl		device_printf(hba->pcidev, "alloc mem bar2 res failed\n");
1523175942Sscottl		return -1;
1524175942Sscottl	}
1525175942Sscottl
1526175942Sscottl	return 0;
1527175942Sscottl}
1528175942Sscottl
1529242214Sdelphijstatic int hptiop_alloc_pci_res_mvfrey(struct hpt_iop_hba *hba)
1530242214Sdelphij{
1531242214Sdelphij	hba->bar0_rid = 0x10;
1532242214Sdelphij	hba->bar0_res = bus_alloc_resource_any(hba->pcidev,
1533242214Sdelphij			SYS_RES_MEMORY, &hba->bar0_rid, RF_ACTIVE);
1534242214Sdelphij
1535242214Sdelphij	if (hba->bar0_res == NULL) {
1536242214Sdelphij		device_printf(hba->pcidev, "failed to get iop bar0.\n");
1537242214Sdelphij		return -1;
1538242214Sdelphij	}
1539242214Sdelphij	hba->bar0t = rman_get_bustag(hba->bar0_res);
1540242214Sdelphij	hba->bar0h = rman_get_bushandle(hba->bar0_res);
1541242214Sdelphij	hba->u.mvfrey.config = (struct hpt_iop_request_get_config *)
1542242214Sdelphij				rman_get_virtual(hba->bar0_res);
1543242214Sdelphij
1544242214Sdelphij	if (!hba->u.mvfrey.config) {
1545242214Sdelphij		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1546242214Sdelphij					hba->bar0_rid, hba->bar0_res);
1547242214Sdelphij		device_printf(hba->pcidev, "alloc bar0 mem res failed\n");
1548242214Sdelphij		return -1;
1549242214Sdelphij	}
1550242214Sdelphij
1551242214Sdelphij	hba->bar2_rid = 0x18;
1552242214Sdelphij	hba->bar2_res = bus_alloc_resource_any(hba->pcidev,
1553242214Sdelphij			SYS_RES_MEMORY, &hba->bar2_rid, RF_ACTIVE);
1554242214Sdelphij
1555242214Sdelphij	if (hba->bar2_res == NULL) {
1556242214Sdelphij		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1557242214Sdelphij					hba->bar0_rid, hba->bar0_res);
1558242214Sdelphij		device_printf(hba->pcidev, "failed to get iop bar2.\n");
1559242214Sdelphij		return -1;
1560242214Sdelphij	}
1561242214Sdelphij
1562242214Sdelphij	hba->bar2t = rman_get_bustag(hba->bar2_res);
1563242214Sdelphij	hba->bar2h = rman_get_bushandle(hba->bar2_res);
1564242214Sdelphij	hba->u.mvfrey.mu =
1565242214Sdelphij					(struct hpt_iopmu_mvfrey *)rman_get_virtual(hba->bar2_res);
1566242214Sdelphij
1567242214Sdelphij	if (!hba->u.mvfrey.mu) {
1568242214Sdelphij		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1569242214Sdelphij					hba->bar0_rid, hba->bar0_res);
1570242214Sdelphij		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1571242214Sdelphij					hba->bar2_rid, hba->bar2_res);
1572242214Sdelphij		device_printf(hba->pcidev, "alloc mem bar2 res failed\n");
1573242214Sdelphij		return -1;
1574242214Sdelphij	}
1575242214Sdelphij
1576242214Sdelphij	return 0;
1577242214Sdelphij}
1578242214Sdelphij
1579175942Sscottlstatic void hptiop_release_pci_res_itl(struct hpt_iop_hba *hba)
1580175942Sscottl{
1581175942Sscottl	if (hba->bar0_res)
1582175942Sscottl		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1583175942Sscottl			hba->bar0_rid, hba->bar0_res);
1584175942Sscottl}
1585175942Sscottl
1586175942Sscottlstatic void hptiop_release_pci_res_mv(struct hpt_iop_hba *hba)
1587175942Sscottl{
1588175942Sscottl	if (hba->bar0_res)
1589175942Sscottl		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1590175942Sscottl			hba->bar0_rid, hba->bar0_res);
1591175942Sscottl	if (hba->bar2_res)
1592175942Sscottl		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1593175942Sscottl			hba->bar2_rid, hba->bar2_res);
1594175942Sscottl}
1595175942Sscottl
1596242214Sdelphijstatic void hptiop_release_pci_res_mvfrey(struct hpt_iop_hba *hba)
1597242214Sdelphij{
1598242214Sdelphij	if (hba->bar0_res)
1599242214Sdelphij		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1600242214Sdelphij			hba->bar0_rid, hba->bar0_res);
1601242214Sdelphij	if (hba->bar2_res)
1602242214Sdelphij		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1603242214Sdelphij			hba->bar2_rid, hba->bar2_res);
1604242214Sdelphij}
1605242214Sdelphij
1606175942Sscottlstatic int hptiop_internal_memalloc_mv(struct hpt_iop_hba *hba)
1607175942Sscottl{
1608175942Sscottl	if (bus_dma_tag_create(hba->parent_dmat,
1609175942Sscottl				1,
1610175942Sscottl				0,
1611175942Sscottl				BUS_SPACE_MAXADDR_32BIT,
1612175942Sscottl				BUS_SPACE_MAXADDR,
1613175942Sscottl				NULL, NULL,
1614175942Sscottl				0x800 - 0x8,
1615175942Sscottl				1,
1616175942Sscottl				BUS_SPACE_MAXSIZE_32BIT,
1617175942Sscottl				BUS_DMA_ALLOCNOW,
1618175942Sscottl#if __FreeBSD_version > 502000
1619175942Sscottl				NULL,
1620175942Sscottl				NULL,
1621175942Sscottl#endif
1622242214Sdelphij				&hba->ctlcfg_dmat)) {
1623175942Sscottl		device_printf(hba->pcidev, "alloc ctlcfg_dmat failed\n");
1624175942Sscottl		return -1;
1625175942Sscottl	}
1626175942Sscottl
1627175942Sscottl	if (bus_dmamem_alloc(hba->ctlcfg_dmat, (void **)&hba->ctlcfg_ptr,
1628175942Sscottl#if __FreeBSD_version>501000
1629175942Sscottl		BUS_DMA_WAITOK | BUS_DMA_COHERENT,
1630175942Sscottl#else
1631175942Sscottl		BUS_DMA_WAITOK,
1632175942Sscottl#endif
1633175942Sscottl		&hba->ctlcfg_dmamap) != 0) {
1634175942Sscottl			device_printf(hba->pcidev,
1635175942Sscottl					"bus_dmamem_alloc failed!\n");
1636175942Sscottl			bus_dma_tag_destroy(hba->ctlcfg_dmat);
1637175942Sscottl			return -1;
1638175942Sscottl	}
1639175942Sscottl
1640175942Sscottl	if (bus_dmamap_load(hba->ctlcfg_dmat,
1641175942Sscottl			hba->ctlcfg_dmamap, hba->ctlcfg_ptr,
1642175942Sscottl			MVIOP_IOCTLCFG_SIZE,
1643175942Sscottl			hptiop_mv_map_ctlcfg, hba, 0)) {
1644175942Sscottl		device_printf(hba->pcidev, "bus_dmamap_load failed!\n");
1645175942Sscottl		if (hba->ctlcfg_dmat)
1646175942Sscottl			bus_dmamem_free(hba->ctlcfg_dmat,
1647175942Sscottl				hba->ctlcfg_ptr, hba->ctlcfg_dmamap);
1648175942Sscottl			bus_dma_tag_destroy(hba->ctlcfg_dmat);
1649175942Sscottl		return -1;
1650175942Sscottl	}
1651175942Sscottl
1652175942Sscottl	return 0;
1653175942Sscottl}
1654175942Sscottl
1655242214Sdelphijstatic int hptiop_internal_memalloc_mvfrey(struct hpt_iop_hba *hba)
1656242214Sdelphij{
1657242214Sdelphij	u_int32_t list_count = BUS_SPACE_RD4_MVFREY2(inbound_conf_ctl);
1658242214Sdelphij
1659242214Sdelphij	list_count >>= 16;
1660242214Sdelphij
1661242214Sdelphij	if (list_count == 0) {
1662242214Sdelphij		return -1;
1663242214Sdelphij	}
1664242214Sdelphij
1665242214Sdelphij	hba->u.mvfrey.list_count = list_count;
1666242214Sdelphij	hba->u.mvfrey.internal_mem_size = 0x800
1667242214Sdelphij							+ list_count * sizeof(struct mvfrey_inlist_entry)
1668242214Sdelphij							+ list_count * sizeof(struct mvfrey_outlist_entry)
1669242214Sdelphij							+ sizeof(int);
1670242214Sdelphij	if (bus_dma_tag_create(hba->parent_dmat,
1671242214Sdelphij				1,
1672242214Sdelphij				0,
1673242214Sdelphij				BUS_SPACE_MAXADDR_32BIT,
1674242214Sdelphij				BUS_SPACE_MAXADDR,
1675242214Sdelphij				NULL, NULL,
1676242214Sdelphij				hba->u.mvfrey.internal_mem_size,
1677242214Sdelphij				1,
1678242214Sdelphij				BUS_SPACE_MAXSIZE_32BIT,
1679242214Sdelphij				BUS_DMA_ALLOCNOW,
1680242214Sdelphij#if __FreeBSD_version > 502000
1681242214Sdelphij				NULL,
1682242214Sdelphij				NULL,
1683242214Sdelphij#endif
1684242214Sdelphij				&hba->ctlcfg_dmat)) {
1685242214Sdelphij		device_printf(hba->pcidev, "alloc ctlcfg_dmat failed\n");
1686242214Sdelphij		return -1;
1687242214Sdelphij	}
1688242214Sdelphij
1689242214Sdelphij	if (bus_dmamem_alloc(hba->ctlcfg_dmat, (void **)&hba->ctlcfg_ptr,
1690242214Sdelphij#if __FreeBSD_version>501000
1691242214Sdelphij		BUS_DMA_WAITOK | BUS_DMA_COHERENT,
1692242214Sdelphij#else
1693242214Sdelphij		BUS_DMA_WAITOK,
1694242214Sdelphij#endif
1695242214Sdelphij		&hba->ctlcfg_dmamap) != 0) {
1696242214Sdelphij			device_printf(hba->pcidev,
1697242214Sdelphij					"bus_dmamem_alloc failed!\n");
1698242214Sdelphij			bus_dma_tag_destroy(hba->ctlcfg_dmat);
1699242214Sdelphij			return -1;
1700242214Sdelphij	}
1701242214Sdelphij
1702242214Sdelphij	if (bus_dmamap_load(hba->ctlcfg_dmat,
1703242214Sdelphij			hba->ctlcfg_dmamap, hba->ctlcfg_ptr,
1704242214Sdelphij			hba->u.mvfrey.internal_mem_size,
1705242214Sdelphij			hptiop_mvfrey_map_ctlcfg, hba, 0)) {
1706242214Sdelphij		device_printf(hba->pcidev, "bus_dmamap_load failed!\n");
1707251162Sdelphij		if (hba->ctlcfg_dmat) {
1708242214Sdelphij			bus_dmamem_free(hba->ctlcfg_dmat,
1709242214Sdelphij				hba->ctlcfg_ptr, hba->ctlcfg_dmamap);
1710242214Sdelphij			bus_dma_tag_destroy(hba->ctlcfg_dmat);
1711251162Sdelphij		}
1712242214Sdelphij		return -1;
1713242214Sdelphij	}
1714242214Sdelphij
1715242214Sdelphij	return 0;
1716242214Sdelphij}
1717242214Sdelphij
1718242214Sdelphijstatic int hptiop_internal_memfree_itl(struct hpt_iop_hba *hba) {
1719242214Sdelphij	return 0;
1720242214Sdelphij}
1721242214Sdelphij
1722175942Sscottlstatic int hptiop_internal_memfree_mv(struct hpt_iop_hba *hba)
1723175942Sscottl{
1724175942Sscottl	if (hba->ctlcfg_dmat) {
1725175942Sscottl		bus_dmamap_unload(hba->ctlcfg_dmat, hba->ctlcfg_dmamap);
1726175942Sscottl		bus_dmamem_free(hba->ctlcfg_dmat,
1727175942Sscottl					hba->ctlcfg_ptr, hba->ctlcfg_dmamap);
1728175942Sscottl		bus_dma_tag_destroy(hba->ctlcfg_dmat);
1729175942Sscottl	}
1730175942Sscottl
1731175942Sscottl	return 0;
1732175942Sscottl}
1733175942Sscottl
1734242214Sdelphijstatic int hptiop_internal_memfree_mvfrey(struct hpt_iop_hba *hba)
1735242214Sdelphij{
1736242214Sdelphij	if (hba->ctlcfg_dmat) {
1737242214Sdelphij		bus_dmamap_unload(hba->ctlcfg_dmat, hba->ctlcfg_dmamap);
1738242214Sdelphij		bus_dmamem_free(hba->ctlcfg_dmat,
1739242214Sdelphij					hba->ctlcfg_ptr, hba->ctlcfg_dmamap);
1740242214Sdelphij		bus_dma_tag_destroy(hba->ctlcfg_dmat);
1741242214Sdelphij	}
1742242214Sdelphij
1743242214Sdelphij	return 0;
1744242214Sdelphij}
1745242214Sdelphij
1746242214Sdelphijstatic int hptiop_reset_comm_mvfrey(struct hpt_iop_hba *hba)
1747242214Sdelphij{
1748242214Sdelphij	u_int32_t i = 100;
1749242214Sdelphij
1750242214Sdelphij	if (hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_RESET_COMM, 3000))
1751242214Sdelphij		return -1;
1752242214Sdelphij
1753242214Sdelphij	/* wait 100ms for MCU ready */
1754242214Sdelphij	while(i--) {
1755242214Sdelphij		DELAY(1000);
1756242214Sdelphij	}
1757242214Sdelphij
1758242214Sdelphij	BUS_SPACE_WRT4_MVFREY2(inbound_base,
1759242214Sdelphij							hba->u.mvfrey.inlist_phy & 0xffffffff);
1760242214Sdelphij	BUS_SPACE_WRT4_MVFREY2(inbound_base_high,
1761242214Sdelphij							(hba->u.mvfrey.inlist_phy >> 16) >> 16);
1762242214Sdelphij
1763242214Sdelphij	BUS_SPACE_WRT4_MVFREY2(outbound_base,
1764242214Sdelphij							hba->u.mvfrey.outlist_phy & 0xffffffff);
1765242214Sdelphij	BUS_SPACE_WRT4_MVFREY2(outbound_base_high,
1766242214Sdelphij							(hba->u.mvfrey.outlist_phy >> 16) >> 16);
1767242214Sdelphij
1768242214Sdelphij	BUS_SPACE_WRT4_MVFREY2(outbound_shadow_base,
1769242214Sdelphij							hba->u.mvfrey.outlist_cptr_phy & 0xffffffff);
1770242214Sdelphij	BUS_SPACE_WRT4_MVFREY2(outbound_shadow_base_high,
1771242214Sdelphij							(hba->u.mvfrey.outlist_cptr_phy >> 16) >> 16);
1772242214Sdelphij
1773242214Sdelphij	hba->u.mvfrey.inlist_wptr = (hba->u.mvfrey.list_count - 1)
1774242214Sdelphij								| CL_POINTER_TOGGLE;
1775242214Sdelphij	*hba->u.mvfrey.outlist_cptr = (hba->u.mvfrey.list_count - 1)
1776242214Sdelphij								| CL_POINTER_TOGGLE;
1777242214Sdelphij	hba->u.mvfrey.outlist_rptr = hba->u.mvfrey.list_count - 1;
1778242214Sdelphij
1779242214Sdelphij	return 0;
1780242214Sdelphij}
1781242214Sdelphij
1782169412Sscottl/*
1783169412Sscottl * CAM driver interface
1784169412Sscottl */
1785169412Sscottlstatic device_method_t driver_methods[] = {
1786169412Sscottl	/* Device interface */
1787169412Sscottl	DEVMETHOD(device_probe,     hptiop_probe),
1788169412Sscottl	DEVMETHOD(device_attach,    hptiop_attach),
1789169412Sscottl	DEVMETHOD(device_detach,    hptiop_detach),
1790169412Sscottl	DEVMETHOD(device_shutdown,  hptiop_shutdown),
1791169412Sscottl	{ 0, 0 }
1792169412Sscottl};
1793169412Sscottl
1794175942Sscottlstatic struct hptiop_adapter_ops hptiop_itl_ops = {
1795242214Sdelphij	.family	           = INTEL_BASED_IOP,
1796175942Sscottl	.iop_wait_ready    = hptiop_wait_ready_itl,
1797175942Sscottl	.internal_memalloc = 0,
1798242214Sdelphij	.internal_memfree  = hptiop_internal_memfree_itl,
1799175942Sscottl	.alloc_pci_res     = hptiop_alloc_pci_res_itl,
1800175942Sscottl	.release_pci_res   = hptiop_release_pci_res_itl,
1801175942Sscottl	.enable_intr       = hptiop_enable_intr_itl,
1802175942Sscottl	.disable_intr      = hptiop_disable_intr_itl,
1803175942Sscottl	.get_config        = hptiop_get_config_itl,
1804175942Sscottl	.set_config        = hptiop_set_config_itl,
1805175942Sscottl	.iop_intr          = hptiop_intr_itl,
1806175942Sscottl	.post_msg          = hptiop_post_msg_itl,
1807175942Sscottl	.post_req          = hptiop_post_req_itl,
1808175942Sscottl	.do_ioctl          = hptiop_do_ioctl_itl,
1809242214Sdelphij	.reset_comm        = 0,
1810175942Sscottl};
1811175942Sscottl
1812175942Sscottlstatic struct hptiop_adapter_ops hptiop_mv_ops = {
1813242214Sdelphij	.family	           = MV_BASED_IOP,
1814175942Sscottl	.iop_wait_ready    = hptiop_wait_ready_mv,
1815175942Sscottl	.internal_memalloc = hptiop_internal_memalloc_mv,
1816175942Sscottl	.internal_memfree  = hptiop_internal_memfree_mv,
1817175942Sscottl	.alloc_pci_res     = hptiop_alloc_pci_res_mv,
1818175942Sscottl	.release_pci_res   = hptiop_release_pci_res_mv,
1819175942Sscottl	.enable_intr       = hptiop_enable_intr_mv,
1820175942Sscottl	.disable_intr      = hptiop_disable_intr_mv,
1821175942Sscottl	.get_config        = hptiop_get_config_mv,
1822175942Sscottl	.set_config        = hptiop_set_config_mv,
1823175942Sscottl	.iop_intr          = hptiop_intr_mv,
1824175942Sscottl	.post_msg          = hptiop_post_msg_mv,
1825175942Sscottl	.post_req          = hptiop_post_req_mv,
1826175942Sscottl	.do_ioctl          = hptiop_do_ioctl_mv,
1827242214Sdelphij	.reset_comm        = 0,
1828175942Sscottl};
1829175942Sscottl
1830242214Sdelphijstatic struct hptiop_adapter_ops hptiop_mvfrey_ops = {
1831242214Sdelphij	.family	           = MVFREY_BASED_IOP,
1832242214Sdelphij	.iop_wait_ready    = hptiop_wait_ready_mvfrey,
1833242214Sdelphij	.internal_memalloc = hptiop_internal_memalloc_mvfrey,
1834242214Sdelphij	.internal_memfree  = hptiop_internal_memfree_mvfrey,
1835242214Sdelphij	.alloc_pci_res     = hptiop_alloc_pci_res_mvfrey,
1836242214Sdelphij	.release_pci_res   = hptiop_release_pci_res_mvfrey,
1837242214Sdelphij	.enable_intr       = hptiop_enable_intr_mvfrey,
1838242214Sdelphij	.disable_intr      = hptiop_disable_intr_mvfrey,
1839242214Sdelphij	.get_config        = hptiop_get_config_mvfrey,
1840242214Sdelphij	.set_config        = hptiop_set_config_mvfrey,
1841242214Sdelphij	.iop_intr          = hptiop_intr_mvfrey,
1842242214Sdelphij	.post_msg          = hptiop_post_msg_mvfrey,
1843242214Sdelphij	.post_req          = hptiop_post_req_mvfrey,
1844242214Sdelphij	.do_ioctl          = hptiop_do_ioctl_mvfrey,
1845242214Sdelphij	.reset_comm        = hptiop_reset_comm_mvfrey,
1846242214Sdelphij};
1847242214Sdelphij
1848169412Sscottlstatic driver_t hptiop_pci_driver = {
1849169412Sscottl	driver_name,
1850169412Sscottl	driver_methods,
1851169412Sscottl	sizeof(struct hpt_iop_hba)
1852169412Sscottl};
1853169412Sscottl
1854169412SscottlDRIVER_MODULE(hptiop, pci, hptiop_pci_driver, hptiop_devclass, 0, 0);
1855236655SeadlerMODULE_DEPEND(hptiop, cam, 1, 1, 1);
1856169412Sscottl
1857169412Sscottlstatic int hptiop_probe(device_t dev)
1858169412Sscottl{
1859169412Sscottl	struct hpt_iop_hba *hba;
1860175942Sscottl	u_int32_t id;
1861175942Sscottl	static char buf[256];
1862175942Sscottl	int sas = 0;
1863175942Sscottl	struct hptiop_adapter_ops *ops;
1864169412Sscottl
1865175942Sscottl	if (pci_get_vendor(dev) != 0x1103)
1866175942Sscottl		return (ENXIO);
1867175942Sscottl
1868175942Sscottl	id = pci_get_device(dev);
1869175942Sscottl
1870175942Sscottl	switch (id) {
1871242214Sdelphij		case 0x4520:
1872252884Sdelphij		case 0x4521:
1873242214Sdelphij		case 0x4522:
1874242214Sdelphij			sas = 1;
1875252884Sdelphij		case 0x3620:
1876252884Sdelphij		case 0x3622:
1877252884Sdelphij		case 0x3640:
1878242214Sdelphij			ops = &hptiop_mvfrey_ops;
1879242214Sdelphij			break;
1880239458Sdelphij		case 0x4210:
1881239458Sdelphij		case 0x4211:
1882239458Sdelphij		case 0x4310:
1883239458Sdelphij		case 0x4311:
1884239458Sdelphij		case 0x4320:
1885224583Sdelphij		case 0x4321:
1886239458Sdelphij 		case 0x4322:
1887175942Sscottl			sas = 1;
1888175942Sscottl		case 0x3220:
1889175942Sscottl		case 0x3320:
1890175942Sscottl		case 0x3410:
1891175942Sscottl		case 0x3520:
1892175942Sscottl		case 0x3510:
1893175942Sscottl		case 0x3511:
1894175942Sscottl		case 0x3521:
1895175942Sscottl		case 0x3522:
1896239458Sdelphij		case 0x3530:
1897175942Sscottl		case 0x3540:
1898239458Sdelphij		case 0x3560:
1899175942Sscottl			ops = &hptiop_itl_ops;
1900175942Sscottl			break;
1901239458Sdelphij		case 0x3020:
1902175942Sscottl		case 0x3120:
1903175942Sscottl		case 0x3122:
1904175942Sscottl			ops = &hptiop_mv_ops;
1905175942Sscottl			break;
1906175942Sscottl		default:
1907175942Sscottl			return (ENXIO);
1908169412Sscottl	}
1909175942Sscottl
1910175942Sscottl	device_printf(dev, "adapter at PCI %d:%d:%d, IRQ %d\n",
1911175942Sscottl		pci_get_bus(dev), pci_get_slot(dev),
1912175942Sscottl		pci_get_function(dev), pci_get_irq(dev));
1913175942Sscottl
1914175942Sscottl	sprintf(buf, "RocketRAID %x %s Controller\n",
1915175942Sscottl				id, sas ? "SAS" : "SATA");
1916175942Sscottl	device_set_desc_copy(dev, buf);
1917175942Sscottl
1918175942Sscottl	hba = (struct hpt_iop_hba *)device_get_softc(dev);
1919175942Sscottl	bzero(hba, sizeof(struct hpt_iop_hba));
1920175942Sscottl	hba->ops = ops;
1921175942Sscottl
1922175942Sscottl	KdPrint(("hba->ops=%p\n", hba->ops));
1923175942Sscottl	return 0;
1924169412Sscottl}
1925169412Sscottl
1926169412Sscottlstatic int hptiop_attach(device_t dev)
1927169412Sscottl{
1928175942Sscottl	struct hpt_iop_hba *hba = (struct hpt_iop_hba *)device_get_softc(dev);
1929169412Sscottl	struct hpt_iop_request_get_config  iop_config;
1930169412Sscottl	struct hpt_iop_request_set_config  set_config;
1931169412Sscottl	int rid = 0;
1932169412Sscottl	struct cam_devq *devq;
1933169412Sscottl	struct ccb_setasync ccb;
1934169412Sscottl	u_int32_t unit = device_get_unit(dev);
1935169412Sscottl
1936175942Sscottl	device_printf(dev, "%d RocketRAID 3xxx/4xxx controller driver %s\n",
1937175942Sscottl			unit, driver_version);
1938169412Sscottl
1939175942Sscottl	KdPrint(("hptiop: attach(%d, %d/%d/%d) ops=%p\n", unit,
1940175942Sscottl		pci_get_bus(dev), pci_get_slot(dev),
1941175942Sscottl		pci_get_function(dev), hba->ops));
1942175942Sscottl
1943169412Sscottl#if __FreeBSD_version >=440000
1944169412Sscottl	pci_enable_busmaster(dev);
1945169412Sscottl#endif
1946169412Sscottl	hba->pcidev = dev;
1947169412Sscottl	hba->pciunit = unit;
1948169412Sscottl
1949175942Sscottl	if (hba->ops->alloc_pci_res(hba))
1950169412Sscottl		return ENXIO;
1951169412Sscottl
1952175942Sscottl	if (hba->ops->iop_wait_ready(hba, 2000)) {
1953175942Sscottl		device_printf(dev, "adapter is not ready\n");
1954175942Sscottl		goto release_pci_res;
1955169412Sscottl	}
1956169412Sscottl
1957169412Sscottl#if (__FreeBSD_version >= 500000)
1958169412Sscottl	mtx_init(&hba->lock, "hptioplock", NULL, MTX_DEF);
1959169412Sscottl#endif
1960169412Sscottl
1961233024Sscottl	if (bus_dma_tag_create(bus_get_dma_tag(dev),/* PCI parent */
1962169412Sscottl			1,  /* alignment */
1963169412Sscottl			0, /* boundary */
1964169412Sscottl			BUS_SPACE_MAXADDR,  /* lowaddr */
1965169412Sscottl			BUS_SPACE_MAXADDR,  /* highaddr */
1966169412Sscottl			NULL, NULL,         /* filter, filterarg */
1967169412Sscottl			BUS_SPACE_MAXSIZE_32BIT,    /* maxsize */
1968169412Sscottl			BUS_SPACE_UNRESTRICTED, /* nsegments */
1969169412Sscottl			BUS_SPACE_MAXSIZE_32BIT,    /* maxsegsize */
1970169412Sscottl			0,      /* flags */
1971169412Sscottl#if __FreeBSD_version>502000
1972169412Sscottl			NULL,   /* lockfunc */
1973169412Sscottl			NULL,       /* lockfuncarg */
1974169412Sscottl#endif
1975169412Sscottl			&hba->parent_dmat   /* tag */))
1976169412Sscottl	{
1977175942Sscottl		device_printf(dev, "alloc parent_dmat failed\n");
1978175942Sscottl		goto release_pci_res;
1979169412Sscottl	}
1980169412Sscottl
1981242214Sdelphij	if (hba->ops->family == MV_BASED_IOP) {
1982175942Sscottl		if (hba->ops->internal_memalloc(hba)) {
1983175942Sscottl			device_printf(dev, "alloc srb_dmat failed\n");
1984175942Sscottl			goto destroy_parent_tag;
1985175942Sscottl		}
1986175942Sscottl	}
1987175942Sscottl
1988175942Sscottl	if (hba->ops->get_config(hba, &iop_config)) {
1989175942Sscottl		device_printf(dev, "get iop config failed.\n");
1990175942Sscottl		goto get_config_failed;
1991175942Sscottl	}
1992175942Sscottl
1993175942Sscottl	hba->firmware_version = iop_config.firmware_version;
1994175942Sscottl	hba->interface_version = iop_config.interface_version;
1995175942Sscottl	hba->max_requests = iop_config.max_requests;
1996175942Sscottl	hba->max_devices = iop_config.max_devices;
1997175942Sscottl	hba->max_request_size = iop_config.request_size;
1998175942Sscottl	hba->max_sg_count = iop_config.max_sg_count;
1999175942Sscottl
2000242214Sdelphij	if (hba->ops->family == MVFREY_BASED_IOP) {
2001242214Sdelphij		if (hba->ops->internal_memalloc(hba)) {
2002242214Sdelphij			device_printf(dev, "alloc srb_dmat failed\n");
2003242214Sdelphij			goto destroy_parent_tag;
2004242214Sdelphij		}
2005242214Sdelphij		if (hba->ops->reset_comm(hba)) {
2006242214Sdelphij			device_printf(dev, "reset comm failed\n");
2007242214Sdelphij			goto get_config_failed;
2008242214Sdelphij		}
2009242214Sdelphij	}
2010242214Sdelphij
2011169412Sscottl	if (bus_dma_tag_create(hba->parent_dmat,/* parent */
2012169412Sscottl			4,  /* alignment */
2013169412Sscottl			BUS_SPACE_MAXADDR_32BIT+1, /* boundary */
2014169412Sscottl			BUS_SPACE_MAXADDR,  /* lowaddr */
2015169412Sscottl			BUS_SPACE_MAXADDR,  /* highaddr */
2016169412Sscottl			NULL, NULL,         /* filter, filterarg */
2017169412Sscottl			PAGE_SIZE * (hba->max_sg_count-1),  /* maxsize */
2018169412Sscottl			hba->max_sg_count,  /* nsegments */
2019169412Sscottl			0x20000,    /* maxsegsize */
2020169412Sscottl			BUS_DMA_ALLOCNOW,       /* flags */
2021169412Sscottl#if __FreeBSD_version>502000
2022169412Sscottl			busdma_lock_mutex,  /* lockfunc */
2023169412Sscottl			&hba->lock,     /* lockfuncarg */
2024169412Sscottl#endif
2025169412Sscottl			&hba->io_dmat   /* tag */))
2026169412Sscottl	{
2027175942Sscottl		device_printf(dev, "alloc io_dmat failed\n");
2028175942Sscottl		goto get_config_failed;
2029169412Sscottl	}
2030169412Sscottl
2031169412Sscottl	if (bus_dma_tag_create(hba->parent_dmat,/* parent */
2032169412Sscottl			1,  /* alignment */
2033169412Sscottl			0, /* boundary */
2034169412Sscottl			BUS_SPACE_MAXADDR_32BIT,    /* lowaddr */
2035169412Sscottl			BUS_SPACE_MAXADDR,  /* highaddr */
2036169412Sscottl			NULL, NULL,         /* filter, filterarg */
2037169412Sscottl			HPT_SRB_MAX_SIZE * HPT_SRB_MAX_QUEUE_SIZE + 0x20,
2038169412Sscottl			1,  /* nsegments */
2039169412Sscottl			BUS_SPACE_MAXSIZE_32BIT,    /* maxsegsize */
2040169412Sscottl			0,      /* flags */
2041169412Sscottl#if __FreeBSD_version>502000
2042169412Sscottl			NULL,   /* lockfunc */
2043169412Sscottl			NULL,       /* lockfuncarg */
2044169412Sscottl#endif
2045169412Sscottl			&hba->srb_dmat  /* tag */))
2046169412Sscottl	{
2047175942Sscottl		device_printf(dev, "alloc srb_dmat failed\n");
2048175942Sscottl		goto destroy_io_dmat;
2049169412Sscottl	}
2050169412Sscottl
2051169412Sscottl	if (bus_dmamem_alloc(hba->srb_dmat, (void **)&hba->uncached_ptr,
2052169412Sscottl#if __FreeBSD_version>501000
2053175942Sscottl			BUS_DMA_WAITOK | BUS_DMA_COHERENT,
2054169412Sscottl#else
2055175942Sscottl			BUS_DMA_WAITOK,
2056169412Sscottl#endif
2057175942Sscottl			&hba->srb_dmamap) != 0)
2058169412Sscottl	{
2059175942Sscottl		device_printf(dev, "srb bus_dmamem_alloc failed!\n");
2060175942Sscottl		goto destroy_srb_dmat;
2061169412Sscottl	}
2062169412Sscottl
2063169412Sscottl	if (bus_dmamap_load(hba->srb_dmat,
2064169412Sscottl			hba->srb_dmamap, hba->uncached_ptr,
2065169412Sscottl			(HPT_SRB_MAX_SIZE * HPT_SRB_MAX_QUEUE_SIZE) + 0x20,
2066169412Sscottl			hptiop_map_srb, hba, 0))
2067169412Sscottl	{
2068175942Sscottl		device_printf(dev, "bus_dmamap_load failed!\n");
2069175942Sscottl		goto srb_dmamem_free;
2070169412Sscottl	}
2071169412Sscottl
2072169412Sscottl	if ((devq = cam_simq_alloc(hba->max_requests - 1 )) == NULL) {
2073175942Sscottl		device_printf(dev, "cam_simq_alloc failed\n");
2074175942Sscottl		goto srb_dmamap_unload;
2075169412Sscottl	}
2076175942Sscottl
2077175942Sscottl#if __FreeBSD_version <700000
2078169412Sscottl	hba->sim = cam_sim_alloc(hptiop_action, hptiop_poll, driver_name,
2079175942Sscottl			hba, unit, hba->max_requests - 1, 1, devq);
2080175942Sscottl#else
2081175942Sscottl	hba->sim = cam_sim_alloc(hptiop_action, hptiop_poll, driver_name,
2082169412Sscottl			hba, unit, &Giant, hba->max_requests - 1, 1, devq);
2083175942Sscottl#endif
2084169412Sscottl	if (!hba->sim) {
2085175942Sscottl		device_printf(dev, "cam_sim_alloc failed\n");
2086169412Sscottl		cam_simq_free(devq);
2087175942Sscottl		goto srb_dmamap_unload;
2088169412Sscottl	}
2089175942Sscottl#if __FreeBSD_version <700000
2090175942Sscottl	if (xpt_bus_register(hba->sim, 0) != CAM_SUCCESS)
2091175942Sscottl#else
2092175942Sscottl	if (xpt_bus_register(hba->sim, dev, 0) != CAM_SUCCESS)
2093175942Sscottl#endif
2094175942Sscottl	{
2095175942Sscottl		device_printf(dev, "xpt_bus_register failed\n");
2096175942Sscottl		goto free_cam_sim;
2097169412Sscottl	}
2098169412Sscottl
2099169412Sscottl	if (xpt_create_path(&hba->path, /*periph */ NULL,
2100169412Sscottl			cam_sim_path(hba->sim), CAM_TARGET_WILDCARD,
2101175942Sscottl			CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
2102175942Sscottl		device_printf(dev, "xpt_create_path failed\n");
2103175942Sscottl		goto deregister_xpt_bus;
2104169412Sscottl	}
2105169412Sscottl
2106169412Sscottl	bzero(&set_config, sizeof(set_config));
2107175942Sscottl	set_config.iop_id = unit;
2108169412Sscottl	set_config.vbus_id = cam_sim_path(hba->sim);
2109169412Sscottl	set_config.max_host_request_size = HPT_SRB_MAX_REQ_SIZE;
2110169412Sscottl
2111175942Sscottl	if (hba->ops->set_config(hba, &set_config)) {
2112175942Sscottl		device_printf(dev, "set iop config failed.\n");
2113175942Sscottl		goto free_hba_path;
2114169412Sscottl	}
2115169412Sscottl
2116169412Sscottl	xpt_setup_ccb(&ccb.ccb_h, hba->path, /*priority*/5);
2117169412Sscottl	ccb.ccb_h.func_code = XPT_SASYNC_CB;
2118169412Sscottl	ccb.event_enable = (AC_FOUND_DEVICE | AC_LOST_DEVICE);
2119169412Sscottl	ccb.callback = hptiop_async;
2120169412Sscottl	ccb.callback_arg = hba->sim;
2121169412Sscottl	xpt_action((union ccb *)&ccb);
2122169412Sscottl
2123169412Sscottl	rid = 0;
2124169412Sscottl	if ((hba->irq_res = bus_alloc_resource(hba->pcidev, SYS_RES_IRQ,
2125169412Sscottl			&rid, 0, ~0ul, 1, RF_SHAREABLE | RF_ACTIVE)) == NULL) {
2126175942Sscottl		device_printf(dev, "allocate irq failed!\n");
2127175942Sscottl		goto free_hba_path;
2128169412Sscottl	}
2129169412Sscottl
2130175942Sscottl#if __FreeBSD_version <700000
2131169412Sscottl	if (bus_setup_intr(hba->pcidev, hba->irq_res, INTR_TYPE_CAM,
2132175942Sscottl				hptiop_pci_intr, hba, &hba->irq_handle))
2133175942Sscottl#else
2134175942Sscottl	if (bus_setup_intr(hba->pcidev, hba->irq_res, INTR_TYPE_CAM,
2135175942Sscottl				NULL, hptiop_pci_intr, hba, &hba->irq_handle))
2136175942Sscottl#endif
2137175942Sscottl	{
2138175942Sscottl		device_printf(dev, "allocate intr function failed!\n");
2139175942Sscottl		goto free_irq_resource;
2140169412Sscottl	}
2141169412Sscottl
2142175942Sscottl	if (hptiop_send_sync_msg(hba,
2143175942Sscottl			IOPMU_INBOUND_MSG0_START_BACKGROUND_TASK, 5000)) {
2144175942Sscottl		device_printf(dev, "fail to start background task\n");
2145175942Sscottl		goto teartown_irq_resource;
2146169412Sscottl	}
2147169412Sscottl
2148175942Sscottl	hba->ops->enable_intr(hba);
2149242214Sdelphij	hba->initialized = 1;
2150175942Sscottl
2151169412Sscottl	hba->ioctl_dev = make_dev(&hptiop_cdevsw, unit,
2152169412Sscottl				UID_ROOT, GID_WHEEL /*GID_OPERATOR*/,
2153169412Sscottl				S_IRUSR | S_IWUSR, "%s%d", driver_name, unit);
2154169412Sscottl
2155169412Sscottl#if __FreeBSD_version < 503000
2156169412Sscottl	hba->ioctl_dev->si_drv1 = hba;
2157169412Sscottl#endif
2158169412Sscottl
2159169412Sscottl	return 0;
2160175942Sscottl
2161175942Sscottl
2162175942Sscottlteartown_irq_resource:
2163175942Sscottl	bus_teardown_intr(dev, hba->irq_res, hba->irq_handle);
2164175942Sscottl
2165175942Sscottlfree_irq_resource:
2166175942Sscottl	bus_release_resource(dev, SYS_RES_IRQ, 0, hba->irq_res);
2167175942Sscottl
2168175942Sscottlfree_hba_path:
2169175942Sscottl	xpt_free_path(hba->path);
2170175942Sscottl
2171175942Sscottlderegister_xpt_bus:
2172175942Sscottl	xpt_bus_deregister(cam_sim_path(hba->sim));
2173175942Sscottl
2174175942Sscottlfree_cam_sim:
2175175942Sscottl	cam_sim_free(hba->sim, /*free devq*/ TRUE);
2176175942Sscottl
2177175942Sscottlsrb_dmamap_unload:
2178175942Sscottl	if (hba->uncached_ptr)
2179175942Sscottl		bus_dmamap_unload(hba->srb_dmat, hba->srb_dmamap);
2180175942Sscottl
2181175942Sscottlsrb_dmamem_free:
2182175942Sscottl	if (hba->uncached_ptr)
2183175942Sscottl		bus_dmamem_free(hba->srb_dmat,
2184175942Sscottl			hba->uncached_ptr, hba->srb_dmamap);
2185175942Sscottl
2186175942Sscottldestroy_srb_dmat:
2187175942Sscottl	if (hba->srb_dmat)
2188175942Sscottl		bus_dma_tag_destroy(hba->srb_dmat);
2189175942Sscottl
2190175942Sscottldestroy_io_dmat:
2191175942Sscottl	if (hba->io_dmat)
2192175942Sscottl		bus_dma_tag_destroy(hba->io_dmat);
2193175942Sscottl
2194175942Sscottlget_config_failed:
2195242214Sdelphij	hba->ops->internal_memfree(hba);
2196175942Sscottl
2197175942Sscottldestroy_parent_tag:
2198175942Sscottl	if (hba->parent_dmat)
2199175942Sscottl		bus_dma_tag_destroy(hba->parent_dmat);
2200175942Sscottl
2201175942Sscottlrelease_pci_res:
2202175942Sscottl	if (hba->ops->release_pci_res)
2203175942Sscottl		hba->ops->release_pci_res(hba);
2204175942Sscottl
2205175942Sscottl	return ENXIO;
2206169412Sscottl}
2207169412Sscottl
2208169412Sscottlstatic int hptiop_detach(device_t dev)
2209169412Sscottl{
2210169412Sscottl	struct hpt_iop_hba * hba = (struct hpt_iop_hba *)device_get_softc(dev);
2211169412Sscottl	int i;
2212169412Sscottl	int error = EBUSY;
2213169412Sscottl
2214169412Sscottl	hptiop_lock_adapter(hba);
2215175942Sscottl	for (i = 0; i < hba->max_devices; i++)
2216175942Sscottl		if (hptiop_os_query_remove_device(hba, i)) {
2217175942Sscottl			device_printf(dev, "%d file system is busy. id=%d",
2218169412Sscottl						hba->pciunit, i);
2219169412Sscottl			goto out;
2220169412Sscottl		}
2221169412Sscottl
2222169412Sscottl	if ((error = hptiop_shutdown(dev)) != 0)
2223169412Sscottl		goto out;
2224175942Sscottl	if (hptiop_send_sync_msg(hba,
2225175942Sscottl		IOPMU_INBOUND_MSG0_STOP_BACKGROUND_TASK, 60000))
2226169412Sscottl		goto out;
2227169412Sscottl
2228169412Sscottl	hptiop_release_resource(hba);
2229169412Sscottl	error = 0;
2230169412Sscottlout:
2231169412Sscottl	hptiop_unlock_adapter(hba);
2232169412Sscottl	return error;
2233169412Sscottl}
2234169412Sscottl
2235169412Sscottlstatic int hptiop_shutdown(device_t dev)
2236169412Sscottl{
2237169412Sscottl	struct hpt_iop_hba * hba = (struct hpt_iop_hba *)device_get_softc(dev);
2238169412Sscottl
2239169412Sscottl	int error = 0;
2240169412Sscottl
2241169412Sscottl	if (hba->flag & HPT_IOCTL_FLAG_OPEN) {
2242175942Sscottl		device_printf(dev, "%d device is busy", hba->pciunit);
2243169412Sscottl		return EBUSY;
2244169412Sscottl	}
2245175942Sscottl
2246175942Sscottl	hba->ops->disable_intr(hba);
2247175942Sscottl
2248175942Sscottl	if (hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_SHUTDOWN, 60000))
2249169412Sscottl		error = EBUSY;
2250169412Sscottl
2251169412Sscottl	return error;
2252169412Sscottl}
2253169412Sscottl
2254169412Sscottlstatic void hptiop_pci_intr(void *arg)
2255169412Sscottl{
2256169412Sscottl	struct hpt_iop_hba * hba = (struct hpt_iop_hba *)arg;
2257169412Sscottl	hptiop_lock_adapter(hba);
2258175942Sscottl	hba->ops->iop_intr(hba);
2259169412Sscottl	hptiop_unlock_adapter(hba);
2260169412Sscottl}
2261169412Sscottl
2262169412Sscottlstatic void hptiop_poll(struct cam_sim *sim)
2263169412Sscottl{
2264169412Sscottl	hptiop_pci_intr(cam_sim_softc(sim));
2265169412Sscottl}
2266169412Sscottl
2267169412Sscottlstatic void hptiop_async(void * callback_arg, u_int32_t code,
2268169412Sscottl					struct cam_path * path, void * arg)
2269169412Sscottl{
2270169412Sscottl}
2271169412Sscottl
2272175942Sscottlstatic void hptiop_enable_intr_itl(struct hpt_iop_hba *hba)
2273169412Sscottl{
2274175942Sscottl	BUS_SPACE_WRT4_ITL(outbound_intmask,
2275169412Sscottl		~(IOPMU_OUTBOUND_INT_POSTQUEUE | IOPMU_OUTBOUND_INT_MSG0));
2276169412Sscottl}
2277169412Sscottl
2278175942Sscottlstatic void hptiop_enable_intr_mv(struct hpt_iop_hba *hba)
2279169412Sscottl{
2280169412Sscottl	u_int32_t int_mask;
2281169412Sscottl
2282175942Sscottl	int_mask = BUS_SPACE_RD4_MV0(outbound_intmask);
2283175942Sscottl
2284175942Sscottl	int_mask |= MVIOP_MU_OUTBOUND_INT_POSTQUEUE
2285175942Sscottl			| MVIOP_MU_OUTBOUND_INT_MSG;
2286175942Sscottl    	BUS_SPACE_WRT4_MV0(outbound_intmask,int_mask);
2287169412Sscottl}
2288169412Sscottl
2289242214Sdelphijstatic void hptiop_enable_intr_mvfrey(struct hpt_iop_hba *hba)
2290242214Sdelphij{
2291242214Sdelphij	BUS_SPACE_WRT4_MVFREY2(f0_doorbell_enable, CPU_TO_F0_DRBL_MSG_A_BIT);
2292242214Sdelphij	BUS_SPACE_RD4_MVFREY2(f0_doorbell_enable);
2293242214Sdelphij
2294242214Sdelphij	BUS_SPACE_WRT4_MVFREY2(isr_enable, 0x1);
2295242214Sdelphij	BUS_SPACE_RD4_MVFREY2(isr_enable);
2296242214Sdelphij
2297242214Sdelphij	BUS_SPACE_WRT4_MVFREY2(pcie_f0_int_enable, 0x1010);
2298242214Sdelphij	BUS_SPACE_RD4_MVFREY2(pcie_f0_int_enable);
2299242214Sdelphij}
2300242214Sdelphij
2301175942Sscottlstatic void hptiop_disable_intr_itl(struct hpt_iop_hba *hba)
2302175942Sscottl{
2303175942Sscottl	u_int32_t int_mask;
2304175942Sscottl
2305175942Sscottl	int_mask = BUS_SPACE_RD4_ITL(outbound_intmask);
2306175942Sscottl
2307175942Sscottl	int_mask |= IOPMU_OUTBOUND_INT_POSTQUEUE | IOPMU_OUTBOUND_INT_MSG0;
2308175942Sscottl	BUS_SPACE_WRT4_ITL(outbound_intmask, int_mask);
2309175942Sscottl	BUS_SPACE_RD4_ITL(outbound_intstatus);
2310175942Sscottl}
2311175942Sscottl
2312175942Sscottlstatic void hptiop_disable_intr_mv(struct hpt_iop_hba *hba)
2313175942Sscottl{
2314175942Sscottl	u_int32_t int_mask;
2315175942Sscottl	int_mask = BUS_SPACE_RD4_MV0(outbound_intmask);
2316175942Sscottl
2317175942Sscottl	int_mask &= ~(MVIOP_MU_OUTBOUND_INT_MSG
2318175942Sscottl			| MVIOP_MU_OUTBOUND_INT_POSTQUEUE);
2319175942Sscottl	BUS_SPACE_WRT4_MV0(outbound_intmask,int_mask);
2320175942Sscottl	BUS_SPACE_RD4_MV0(outbound_intmask);
2321175942Sscottl}
2322175942Sscottl
2323242214Sdelphijstatic void hptiop_disable_intr_mvfrey(struct hpt_iop_hba *hba)
2324169412Sscottl{
2325242214Sdelphij	BUS_SPACE_WRT4_MVFREY2(f0_doorbell_enable, 0);
2326242214Sdelphij	BUS_SPACE_RD4_MVFREY2(f0_doorbell_enable);
2327242214Sdelphij
2328242214Sdelphij	BUS_SPACE_WRT4_MVFREY2(isr_enable, 0);
2329242214Sdelphij	BUS_SPACE_RD4_MVFREY2(isr_enable);
2330242214Sdelphij
2331242214Sdelphij	BUS_SPACE_WRT4_MVFREY2(pcie_f0_int_enable, 0);
2332242214Sdelphij	BUS_SPACE_RD4_MVFREY2(pcie_f0_int_enable);
2333169412Sscottl}
2334169412Sscottl
2335242214Sdelphijstatic void hptiop_reset_adapter(void *argv)
2336242214Sdelphij{
2337242214Sdelphij	struct hpt_iop_hba * hba = (struct hpt_iop_hba *)argv;
2338242214Sdelphij	if (hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_RESET, 60000))
2339242214Sdelphij		return;
2340242214Sdelphij	hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_START_BACKGROUND_TASK, 5000);
2341242214Sdelphij}
2342242214Sdelphij
2343169412Sscottlstatic void *hptiop_get_srb(struct hpt_iop_hba * hba)
2344169412Sscottl{
2345169412Sscottl	struct hpt_iop_srb * srb;
2346169412Sscottl
2347169412Sscottl	if (hba->srb_list) {
2348169412Sscottl		srb = hba->srb_list;
2349169412Sscottl		hba->srb_list = srb->next;
2350175942Sscottl		return srb;
2351169412Sscottl	}
2352169412Sscottl
2353175942Sscottl	return NULL;
2354169412Sscottl}
2355169412Sscottl
2356175942Sscottlstatic void hptiop_free_srb(struct hpt_iop_hba *hba, struct hpt_iop_srb *srb)
2357169412Sscottl{
2358169412Sscottl	srb->next = hba->srb_list;
2359169412Sscottl	hba->srb_list = srb;
2360169412Sscottl}
2361169412Sscottl
2362169412Sscottlstatic void hptiop_action(struct cam_sim *sim, union ccb *ccb)
2363169412Sscottl{
2364169412Sscottl	struct hpt_iop_hba * hba = (struct hpt_iop_hba *)cam_sim_softc(sim);
2365169412Sscottl	struct hpt_iop_srb * srb;
2366251874Sscottl	int error;
2367169412Sscottl
2368169412Sscottl	switch (ccb->ccb_h.func_code) {
2369169412Sscottl
2370169412Sscottl	case XPT_SCSI_IO:
2371169412Sscottl		hptiop_lock_adapter(hba);
2372169412Sscottl		if (ccb->ccb_h.target_lun != 0 ||
2373175942Sscottl			ccb->ccb_h.target_id >= hba->max_devices ||
2374169412Sscottl			(ccb->ccb_h.flags & CAM_CDB_PHYS))
2375169412Sscottl		{
2376169412Sscottl			ccb->ccb_h.status = CAM_TID_INVALID;
2377169412Sscottl			xpt_done(ccb);
2378169412Sscottl			goto scsi_done;
2379169412Sscottl		}
2380169412Sscottl
2381169412Sscottl		if ((srb = hptiop_get_srb(hba)) == NULL) {
2382175942Sscottl			device_printf(hba->pcidev, "srb allocated failed");
2383169412Sscottl			ccb->ccb_h.status = CAM_REQ_CMP_ERR;
2384169412Sscottl			xpt_done(ccb);
2385169412Sscottl			goto scsi_done;
2386169412Sscottl		}
2387169412Sscottl
2388169412Sscottl		srb->ccb = ccb;
2389251874Sscottl		error = bus_dmamap_load_ccb(hba->io_dmat,
2390251874Sscottl					    srb->dma_map,
2391251874Sscottl					    ccb,
2392251874Sscottl					    hptiop_post_scsi_command,
2393251874Sscottl					    srb,
2394251874Sscottl					    0);
2395169412Sscottl
2396251874Sscottl		if (error && error != EINPROGRESS) {
2397251874Sscottl			device_printf(hba->pcidev,
2398251874Sscottl				"%d bus_dmamap_load error %d",
2399251874Sscottl				hba->pciunit, error);
2400251874Sscottl			xpt_freeze_simq(hba->sim, 1);
2401251874Sscottl			ccb->ccb_h.status = CAM_REQ_CMP_ERR;
2402251874Sscottl			hptiop_free_srb(hba, srb);
2403251874Sscottl			xpt_done(ccb);
2404251874Sscottl			goto scsi_done;
2405169412Sscottl		}
2406169412Sscottl
2407169412Sscottlscsi_done:
2408169412Sscottl		hptiop_unlock_adapter(hba);
2409169412Sscottl		return;
2410169412Sscottl
2411169412Sscottl	case XPT_RESET_BUS:
2412175942Sscottl		device_printf(hba->pcidev, "reset adapter");
2413169412Sscottl		hptiop_lock_adapter(hba);
2414169412Sscottl		hba->msg_done = 0;
2415169412Sscottl		hptiop_reset_adapter(hba);
2416169412Sscottl		hptiop_unlock_adapter(hba);
2417169412Sscottl		break;
2418169412Sscottl
2419169412Sscottl	case XPT_GET_TRAN_SETTINGS:
2420169412Sscottl	case XPT_SET_TRAN_SETTINGS:
2421169412Sscottl		ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
2422169412Sscottl		break;
2423169412Sscottl
2424169412Sscottl	case XPT_CALC_GEOMETRY:
2425230719Smarius#if __FreeBSD_version >= 500000
2426230719Smarius		cam_calc_geometry(&ccb->ccg, 1);
2427230719Smarius#else
2428169412Sscottl		ccb->ccg.heads = 255;
2429169412Sscottl		ccb->ccg.secs_per_track = 63;
2430169412Sscottl		ccb->ccg.cylinders = ccb->ccg.volume_size /
2431169412Sscottl				(ccb->ccg.heads * ccb->ccg.secs_per_track);
2432169412Sscottl		ccb->ccb_h.status = CAM_REQ_CMP;
2433230719Smarius#endif
2434169412Sscottl		break;
2435169412Sscottl
2436169412Sscottl	case XPT_PATH_INQ:
2437169412Sscottl	{
2438169412Sscottl		struct ccb_pathinq *cpi = &ccb->cpi;
2439169412Sscottl
2440169412Sscottl		cpi->version_num = 1;
2441169412Sscottl		cpi->hba_inquiry = PI_SDTR_ABLE;
2442169412Sscottl		cpi->target_sprt = 0;
2443169412Sscottl		cpi->hba_misc = PIM_NOBUSRESET;
2444169412Sscottl		cpi->hba_eng_cnt = 0;
2445175942Sscottl		cpi->max_target = hba->max_devices;
2446169412Sscottl		cpi->max_lun = 0;
2447169412Sscottl		cpi->unit_number = cam_sim_unit(sim);
2448169412Sscottl		cpi->bus_id = cam_sim_bus(sim);
2449175942Sscottl		cpi->initiator_id = hba->max_devices;
2450169412Sscottl		cpi->base_transfer_speed = 3300;
2451169412Sscottl
2452169412Sscottl		strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
2453169412Sscottl		strncpy(cpi->hba_vid, "HPT   ", HBA_IDLEN);
2454169412Sscottl		strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
2455209340Smav		cpi->transport = XPORT_SPI;
2456209340Smav		cpi->transport_version = 2;
2457209340Smav		cpi->protocol = PROTO_SCSI;
2458209340Smav		cpi->protocol_version = SCSI_REV_2;
2459169412Sscottl		cpi->ccb_h.status = CAM_REQ_CMP;
2460169412Sscottl		break;
2461169412Sscottl	}
2462169412Sscottl
2463169412Sscottl	default:
2464169412Sscottl		ccb->ccb_h.status = CAM_REQ_INVALID;
2465169412Sscottl		break;
2466169412Sscottl	}
2467169412Sscottl
2468169412Sscottl	xpt_done(ccb);
2469169412Sscottl	return;
2470169412Sscottl}
2471169412Sscottl
2472175942Sscottlstatic void hptiop_post_req_itl(struct hpt_iop_hba *hba,
2473175942Sscottl				struct hpt_iop_srb *srb,
2474175942Sscottl				bus_dma_segment_t *segs, int nsegs)
2475169412Sscottl{
2476169412Sscottl	int idx;
2477169412Sscottl	union ccb *ccb = srb->ccb;
2478169412Sscottl	u_int8_t *cdb;
2479169412Sscottl
2480175942Sscottl	if (ccb->ccb_h.flags & CAM_CDB_POINTER)
2481175942Sscottl		cdb = ccb->csio.cdb_io.cdb_ptr;
2482175942Sscottl	else
2483175942Sscottl		cdb = ccb->csio.cdb_io.cdb_bytes;
2484169412Sscottl
2485175942Sscottl	KdPrint(("ccb=%p %x-%x-%x\n",
2486175942Sscottl		ccb, *(u_int32_t *)cdb, *((u_int32_t *)cdb+1), *((u_int32_t *)cdb+2)));
2487169412Sscottl
2488169412Sscottl	if (srb->srb_flag & HPT_SRB_FLAG_HIGH_MEM_ACESS) {
2489175942Sscottl		u_int32_t iop_req32;
2490175942Sscottl		struct hpt_iop_request_scsi_command req;
2491169412Sscottl
2492175942Sscottl		iop_req32 = BUS_SPACE_RD4_ITL(inbound_queue);
2493175942Sscottl
2494175942Sscottl		if (iop_req32 == IOPMU_QUEUE_EMPTY) {
2495175942Sscottl			device_printf(hba->pcidev, "invaild req offset\n");
2496175942Sscottl			ccb->ccb_h.status = CAM_BUSY;
2497175942Sscottl			bus_dmamap_unload(hba->io_dmat, srb->dma_map);
2498175942Sscottl			hptiop_free_srb(hba, srb);
2499175942Sscottl			xpt_done(ccb);
2500175942Sscottl			return;
2501169412Sscottl		}
2502175942Sscottl
2503175942Sscottl		if (ccb->csio.dxfer_len && nsegs > 0) {
2504175942Sscottl			struct hpt_iopsg *psg = req.sg_list;
2505175942Sscottl			for (idx = 0; idx < nsegs; idx++, psg++) {
2506175942Sscottl				psg->pci_address = (u_int64_t)segs[idx].ds_addr;
2507175942Sscottl				psg->size = segs[idx].ds_len;
2508175942Sscottl				psg->eot = 0;
2509175942Sscottl			}
2510175942Sscottl			psg[-1].eot = 1;
2511175942Sscottl		}
2512175942Sscottl
2513175942Sscottl		bcopy(cdb, req.cdb, ccb->csio.cdb_len);
2514175942Sscottl
2515242214Sdelphij		req.header.size =
2516242214Sdelphij				offsetof(struct hpt_iop_request_scsi_command, sg_list)
2517175942Sscottl				+ nsegs*sizeof(struct hpt_iopsg);
2518175942Sscottl		req.header.type = IOP_REQUEST_TYPE_SCSI_COMMAND;
2519175942Sscottl		req.header.flags = 0;
2520175942Sscottl		req.header.result = IOP_RESULT_PENDING;
2521175942Sscottl		req.header.context = (u_int64_t)(unsigned long)srb;
2522175942Sscottl		req.dataxfer_length = ccb->csio.dxfer_len;
2523175942Sscottl		req.channel =  0;
2524175942Sscottl		req.target =  ccb->ccb_h.target_id;
2525175942Sscottl		req.lun =  ccb->ccb_h.target_lun;
2526175942Sscottl
2527175942Sscottl		bus_space_write_region_1(hba->bar0t, hba->bar0h, iop_req32,
2528175942Sscottl			(u_int8_t *)&req, req.header.size);
2529175942Sscottl
2530175942Sscottl		if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
2531175942Sscottl			bus_dmamap_sync(hba->io_dmat,
2532175942Sscottl				srb->dma_map, BUS_DMASYNC_PREREAD);
2533175942Sscottl		}
2534175942Sscottl		else if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT)
2535175942Sscottl			bus_dmamap_sync(hba->io_dmat,
2536175942Sscottl				srb->dma_map, BUS_DMASYNC_PREWRITE);
2537175942Sscottl
2538175942Sscottl		BUS_SPACE_WRT4_ITL(inbound_queue,iop_req32);
2539175942Sscottl	} else {
2540175942Sscottl		struct hpt_iop_request_scsi_command *req;
2541175942Sscottl
2542169412Sscottl		req = (struct hpt_iop_request_scsi_command *)srb;
2543175942Sscottl		if (ccb->csio.dxfer_len && nsegs > 0) {
2544175942Sscottl			struct hpt_iopsg *psg = req->sg_list;
2545175942Sscottl			for (idx = 0; idx < nsegs; idx++, psg++) {
2546175942Sscottl				psg->pci_address =
2547175942Sscottl					(u_int64_t)segs[idx].ds_addr;
2548175942Sscottl				psg->size = segs[idx].ds_len;
2549175942Sscottl				psg->eot = 0;
2550175942Sscottl			}
2551175942Sscottl			psg[-1].eot = 1;
2552175942Sscottl		}
2553169412Sscottl
2554175942Sscottl		bcopy(cdb, req->cdb, ccb->csio.cdb_len);
2555175942Sscottl
2556175942Sscottl		req->header.type = IOP_REQUEST_TYPE_SCSI_COMMAND;
2557175942Sscottl		req->header.result = IOP_RESULT_PENDING;
2558175942Sscottl		req->dataxfer_length = ccb->csio.dxfer_len;
2559175942Sscottl		req->channel =  0;
2560175942Sscottl		req->target =  ccb->ccb_h.target_id;
2561175942Sscottl		req->lun =  ccb->ccb_h.target_lun;
2562242214Sdelphij		req->header.size =
2563242214Sdelphij			offsetof(struct hpt_iop_request_scsi_command, sg_list)
2564175942Sscottl			+ nsegs*sizeof(struct hpt_iopsg);
2565175942Sscottl		req->header.context = (u_int64_t)srb->index |
2566175942Sscottl						IOPMU_QUEUE_ADDR_HOST_BIT;
2567175942Sscottl		req->header.flags = IOP_REQUEST_FLAG_OUTPUT_CONTEXT;
2568175942Sscottl
2569175942Sscottl		if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
2570175942Sscottl			bus_dmamap_sync(hba->io_dmat,
2571175942Sscottl				srb->dma_map, BUS_DMASYNC_PREREAD);
2572175942Sscottl		}else if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) {
2573175942Sscottl			bus_dmamap_sync(hba->io_dmat,
2574175942Sscottl				srb->dma_map, BUS_DMASYNC_PREWRITE);
2575175942Sscottl		}
2576175942Sscottl
2577175942Sscottl		if (hba->firmware_version > 0x01020000
2578175942Sscottl			|| hba->interface_version > 0x01020000) {
2579175942Sscottl			u_int32_t size_bits;
2580175942Sscottl
2581175942Sscottl			if (req->header.size < 256)
2582175942Sscottl				size_bits = IOPMU_QUEUE_REQUEST_SIZE_BIT;
2583175942Sscottl			else if (req->header.size < 512)
2584175942Sscottl				size_bits = IOPMU_QUEUE_ADDR_HOST_BIT;
2585175942Sscottl			else
2586175942Sscottl				size_bits = IOPMU_QUEUE_REQUEST_SIZE_BIT
2587175942Sscottl						| IOPMU_QUEUE_ADDR_HOST_BIT;
2588175942Sscottl
2589175942Sscottl			BUS_SPACE_WRT4_ITL(inbound_queue,
2590175942Sscottl				(u_int32_t)srb->phy_addr | size_bits);
2591175942Sscottl		} else
2592175942Sscottl			BUS_SPACE_WRT4_ITL(inbound_queue, (u_int32_t)srb->phy_addr
2593175942Sscottl				|IOPMU_QUEUE_ADDR_HOST_BIT);
2594175942Sscottl	}
2595175942Sscottl}
2596175942Sscottl
2597175942Sscottlstatic void hptiop_post_req_mv(struct hpt_iop_hba *hba,
2598175942Sscottl				struct hpt_iop_srb *srb,
2599175942Sscottl				bus_dma_segment_t *segs, int nsegs)
2600175942Sscottl{
2601175942Sscottl	int idx, size;
2602175942Sscottl	union ccb *ccb = srb->ccb;
2603175942Sscottl	u_int8_t *cdb;
2604175942Sscottl	struct hpt_iop_request_scsi_command *req;
2605175942Sscottl	u_int64_t req_phy;
2606175942Sscottl
2607175942Sscottl    	req = (struct hpt_iop_request_scsi_command *)srb;
2608175942Sscottl	req_phy = srb->phy_addr;
2609175942Sscottl
2610169412Sscottl	if (ccb->csio.dxfer_len && nsegs > 0) {
2611169412Sscottl		struct hpt_iopsg *psg = req->sg_list;
2612169412Sscottl		for (idx = 0; idx < nsegs; idx++, psg++) {
2613169412Sscottl			psg->pci_address = (u_int64_t)segs[idx].ds_addr;
2614169412Sscottl			psg->size = segs[idx].ds_len;
2615169412Sscottl			psg->eot = 0;
2616169412Sscottl		}
2617169412Sscottl		psg[-1].eot = 1;
2618169412Sscottl	}
2619169412Sscottl	if (ccb->ccb_h.flags & CAM_CDB_POINTER)
2620169412Sscottl		cdb = ccb->csio.cdb_io.cdb_ptr;
2621169412Sscottl	else
2622169412Sscottl		cdb = ccb->csio.cdb_io.cdb_bytes;
2623169412Sscottl
2624169412Sscottl	bcopy(cdb, req->cdb, ccb->csio.cdb_len);
2625169412Sscottl	req->header.type = IOP_REQUEST_TYPE_SCSI_COMMAND;
2626169412Sscottl	req->header.result = IOP_RESULT_PENDING;
2627169412Sscottl	req->dataxfer_length = ccb->csio.dxfer_len;
2628175942Sscottl	req->channel = 0;
2629169412Sscottl	req->target =  ccb->ccb_h.target_id;
2630169412Sscottl	req->lun =  ccb->ccb_h.target_lun;
2631169412Sscottl	req->header.size = sizeof(struct hpt_iop_request_scsi_command)
2632175942Sscottl				- sizeof(struct hpt_iopsg)
2633175942Sscottl				+ nsegs * sizeof(struct hpt_iopsg);
2634169412Sscottl	if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
2635169412Sscottl		bus_dmamap_sync(hba->io_dmat,
2636175942Sscottl			srb->dma_map, BUS_DMASYNC_PREREAD);
2637169412Sscottl	}
2638169412Sscottl	else if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT)
2639169412Sscottl		bus_dmamap_sync(hba->io_dmat,
2640175942Sscottl			srb->dma_map, BUS_DMASYNC_PREWRITE);
2641175942Sscottl	req->header.context = (u_int64_t)srb->index
2642175942Sscottl					<< MVIOP_REQUEST_NUMBER_START_BIT
2643175942Sscottl					| MVIOP_CMD_TYPE_SCSI;
2644175942Sscottl	req->header.flags = IOP_REQUEST_FLAG_OUTPUT_CONTEXT;
2645175942Sscottl	size = req->header.size >> 8;
2646175942Sscottl	hptiop_mv_inbound_write(req_phy
2647175942Sscottl			| MVIOP_MU_QUEUE_ADDR_HOST_BIT
2648175942Sscottl			| (size > 3 ? 3 : size), hba);
2649169412Sscottl}
2650169412Sscottl
2651242214Sdelphijstatic void hptiop_post_req_mvfrey(struct hpt_iop_hba *hba,
2652242214Sdelphij				struct hpt_iop_srb *srb,
2653242214Sdelphij				bus_dma_segment_t *segs, int nsegs)
2654242214Sdelphij{
2655242214Sdelphij	int idx, index;
2656242214Sdelphij	union ccb *ccb = srb->ccb;
2657242214Sdelphij	u_int8_t *cdb;
2658242214Sdelphij	struct hpt_iop_request_scsi_command *req;
2659242214Sdelphij	u_int64_t req_phy;
2660242214Sdelphij
2661242214Sdelphij	req = (struct hpt_iop_request_scsi_command *)srb;
2662242214Sdelphij	req_phy = srb->phy_addr;
2663242214Sdelphij
2664242214Sdelphij	if (ccb->csio.dxfer_len && nsegs > 0) {
2665242214Sdelphij		struct hpt_iopsg *psg = req->sg_list;
2666242214Sdelphij		for (idx = 0; idx < nsegs; idx++, psg++) {
2667242214Sdelphij			psg->pci_address = (u_int64_t)segs[idx].ds_addr | 1;
2668242214Sdelphij			psg->size = segs[idx].ds_len;
2669242214Sdelphij			psg->eot = 0;
2670242214Sdelphij		}
2671242214Sdelphij		psg[-1].eot = 1;
2672242214Sdelphij	}
2673242214Sdelphij	if (ccb->ccb_h.flags & CAM_CDB_POINTER)
2674242214Sdelphij		cdb = ccb->csio.cdb_io.cdb_ptr;
2675242214Sdelphij	else
2676242214Sdelphij		cdb = ccb->csio.cdb_io.cdb_bytes;
2677242214Sdelphij
2678242214Sdelphij	bcopy(cdb, req->cdb, ccb->csio.cdb_len);
2679242214Sdelphij	req->header.type = IOP_REQUEST_TYPE_SCSI_COMMAND;
2680242214Sdelphij	req->header.result = IOP_RESULT_PENDING;
2681242214Sdelphij	req->dataxfer_length = ccb->csio.dxfer_len;
2682242214Sdelphij	req->channel = 0;
2683242214Sdelphij	req->target = ccb->ccb_h.target_id;
2684242214Sdelphij	req->lun = ccb->ccb_h.target_lun;
2685242214Sdelphij	req->header.size = sizeof(struct hpt_iop_request_scsi_command)
2686242214Sdelphij				- sizeof(struct hpt_iopsg)
2687242214Sdelphij				+ nsegs * sizeof(struct hpt_iopsg);
2688242214Sdelphij	if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
2689242214Sdelphij		bus_dmamap_sync(hba->io_dmat,
2690242214Sdelphij			srb->dma_map, BUS_DMASYNC_PREREAD);
2691242214Sdelphij	}
2692242214Sdelphij	else if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT)
2693242214Sdelphij		bus_dmamap_sync(hba->io_dmat,
2694242214Sdelphij			srb->dma_map, BUS_DMASYNC_PREWRITE);
2695242214Sdelphij
2696242214Sdelphij	req->header.flags = IOP_REQUEST_FLAG_OUTPUT_CONTEXT
2697242214Sdelphij						| IOP_REQUEST_FLAG_ADDR_BITS
2698242214Sdelphij						| ((req_phy >> 16) & 0xffff0000);
2699242214Sdelphij	req->header.context = ((req_phy & 0xffffffff) << 32 )
2700242214Sdelphij						| srb->index << 4
2701242214Sdelphij						| IOPMU_QUEUE_ADDR_HOST_BIT | req->header.type;
2702242214Sdelphij
2703242214Sdelphij	hba->u.mvfrey.inlist_wptr++;
2704242214Sdelphij	index = hba->u.mvfrey.inlist_wptr & 0x3fff;
2705242214Sdelphij
2706242214Sdelphij	if (index == hba->u.mvfrey.list_count) {
2707242214Sdelphij		index = 0;
2708242214Sdelphij		hba->u.mvfrey.inlist_wptr &= ~0x3fff;
2709242214Sdelphij		hba->u.mvfrey.inlist_wptr ^= CL_POINTER_TOGGLE;
2710242214Sdelphij	}
2711242214Sdelphij
2712242214Sdelphij	hba->u.mvfrey.inlist[index].addr = req_phy;
2713242214Sdelphij	hba->u.mvfrey.inlist[index].intrfc_len = (req->header.size + 3) / 4;
2714242214Sdelphij
2715242214Sdelphij	BUS_SPACE_WRT4_MVFREY2(inbound_write_ptr, hba->u.mvfrey.inlist_wptr);
2716242214Sdelphij	BUS_SPACE_RD4_MVFREY2(inbound_write_ptr);
2717242214Sdelphij
2718242214Sdelphij	if (req->header.type == IOP_REQUEST_TYPE_SCSI_COMMAND) {
2719242214Sdelphij		ccb->ccb_h.timeout_ch = timeout(hptiop_reset_adapter, hba, 20*hz);
2720242214Sdelphij	}
2721242214Sdelphij}
2722242214Sdelphij
2723175942Sscottlstatic void hptiop_post_scsi_command(void *arg, bus_dma_segment_t *segs,
2724175942Sscottl					int nsegs, int error)
2725169412Sscottl{
2726175942Sscottl	struct hpt_iop_srb *srb = (struct hpt_iop_srb *)arg;
2727175942Sscottl	union ccb *ccb = srb->ccb;
2728175942Sscottl	struct hpt_iop_hba *hba = srb->hba;
2729169412Sscottl
2730175942Sscottl	if (error || nsegs > hba->max_sg_count) {
2731175942Sscottl		KdPrint(("hptiop: func_code=%x tid=%x lun=%x nsegs=%d\n",
2732175942Sscottl			ccb->ccb_h.func_code,
2733175942Sscottl			ccb->ccb_h.target_id,
2734175942Sscottl			ccb->ccb_h.target_lun, nsegs));
2735175942Sscottl		ccb->ccb_h.status = CAM_BUSY;
2736175942Sscottl		bus_dmamap_unload(hba->io_dmat, srb->dma_map);
2737169412Sscottl		hptiop_free_srb(hba, srb);
2738169412Sscottl		xpt_done(ccb);
2739175942Sscottl		return;
2740169412Sscottl	}
2741175942Sscottl
2742175942Sscottl	hba->ops->post_req(hba, srb, segs, nsegs);
2743169412Sscottl}
2744169412Sscottl
2745175942Sscottlstatic void hptiop_mv_map_ctlcfg(void *arg, bus_dma_segment_t *segs,
2746175942Sscottl				int nsegs, int error)
2747175942Sscottl{
2748175942Sscottl	struct hpt_iop_hba *hba = (struct hpt_iop_hba *)arg;
2749175942Sscottl	hba->ctlcfgcmd_phy = ((u_int64_t)segs->ds_addr + 0x1F)
2750175942Sscottl				& ~(u_int64_t)0x1F;
2751175942Sscottl	hba->ctlcfg_ptr = (u_int8_t *)(((unsigned long)hba->ctlcfg_ptr + 0x1F)
2752175942Sscottl				& ~0x1F);
2753175942Sscottl}
2754175942Sscottl
2755242214Sdelphijstatic void hptiop_mvfrey_map_ctlcfg(void *arg, bus_dma_segment_t *segs,
2756242214Sdelphij				int nsegs, int error)
2757242214Sdelphij{
2758242214Sdelphij	struct hpt_iop_hba *hba = (struct hpt_iop_hba *)arg;
2759242214Sdelphij	char *p;
2760242214Sdelphij	u_int64_t phy;
2761242214Sdelphij	u_int32_t list_count = hba->u.mvfrey.list_count;
2762242214Sdelphij
2763242214Sdelphij	phy = ((u_int64_t)segs->ds_addr + 0x1F)
2764242214Sdelphij				& ~(u_int64_t)0x1F;
2765242214Sdelphij	p = (u_int8_t *)(((unsigned long)hba->ctlcfg_ptr + 0x1F)
2766242214Sdelphij				& ~0x1F);
2767242214Sdelphij
2768242214Sdelphij	hba->ctlcfgcmd_phy = phy;
2769242214Sdelphij	hba->ctlcfg_ptr = p;
2770242214Sdelphij
2771242214Sdelphij	p += 0x800;
2772242214Sdelphij	phy += 0x800;
2773242214Sdelphij
2774242214Sdelphij	hba->u.mvfrey.inlist = (struct mvfrey_inlist_entry *)p;
2775242214Sdelphij	hba->u.mvfrey.inlist_phy = phy;
2776242214Sdelphij
2777242214Sdelphij	p += list_count * sizeof(struct mvfrey_inlist_entry);
2778242214Sdelphij	phy += list_count * sizeof(struct mvfrey_inlist_entry);
2779242214Sdelphij
2780242214Sdelphij	hba->u.mvfrey.outlist = (struct mvfrey_outlist_entry *)p;
2781242214Sdelphij	hba->u.mvfrey.outlist_phy = phy;
2782242214Sdelphij
2783242214Sdelphij	p += list_count * sizeof(struct mvfrey_outlist_entry);
2784242214Sdelphij	phy += list_count * sizeof(struct mvfrey_outlist_entry);
2785242214Sdelphij
2786242214Sdelphij	hba->u.mvfrey.outlist_cptr = (u_int32_t *)p;
2787242214Sdelphij	hba->u.mvfrey.outlist_cptr_phy = phy;
2788242214Sdelphij}
2789242214Sdelphij
2790169412Sscottlstatic void hptiop_map_srb(void *arg, bus_dma_segment_t *segs,
2791175942Sscottl				int nsegs, int error)
2792169412Sscottl{
2793169412Sscottl	struct hpt_iop_hba * hba = (struct hpt_iop_hba *)arg;
2794169412Sscottl	bus_addr_t phy_addr = (segs->ds_addr + 0x1F) & ~(bus_addr_t)0x1F;
2795169412Sscottl	struct hpt_iop_srb *srb, *tmp_srb;
2796169412Sscottl	int i;
2797169412Sscottl
2798169412Sscottl	if (error || nsegs == 0) {
2799175942Sscottl		device_printf(hba->pcidev, "hptiop_map_srb error");
2800169412Sscottl		return;
2801169412Sscottl	}
2802169412Sscottl
2803169412Sscottl	/* map srb */
2804169412Sscottl	srb = (struct hpt_iop_srb *)
2805175942Sscottl		(((unsigned long)hba->uncached_ptr + 0x1F)
2806175942Sscottl		& ~(unsigned long)0x1F);
2807169412Sscottl
2808169412Sscottl	for (i = 0; i < HPT_SRB_MAX_QUEUE_SIZE; i++) {
2809169412Sscottl		tmp_srb = (struct hpt_iop_srb *)
2810169412Sscottl					((char *)srb + i * HPT_SRB_MAX_SIZE);
2811169412Sscottl		if (((unsigned long)tmp_srb & 0x1F) == 0) {
2812169412Sscottl			if (bus_dmamap_create(hba->io_dmat,
2813169412Sscottl						0, &tmp_srb->dma_map)) {
2814175942Sscottl				device_printf(hba->pcidev, "dmamap create failed");
2815169412Sscottl				return;
2816169412Sscottl			}
2817169412Sscottl
2818169412Sscottl			bzero(tmp_srb, sizeof(struct hpt_iop_srb));
2819169412Sscottl			tmp_srb->hba = hba;
2820169412Sscottl			tmp_srb->index = i;
2821175942Sscottl			if (hba->ctlcfg_ptr == 0) {/*itl iop*/
2822175942Sscottl				tmp_srb->phy_addr = (u_int64_t)(u_int32_t)
2823175942Sscottl							(phy_addr >> 5);
2824175942Sscottl				if (phy_addr & IOPMU_MAX_MEM_SUPPORT_MASK_32G)
2825175942Sscottl					tmp_srb->srb_flag =
2826175942Sscottl						HPT_SRB_FLAG_HIGH_MEM_ACESS;
2827175942Sscottl			} else {
2828175942Sscottl				tmp_srb->phy_addr = phy_addr;
2829175942Sscottl			}
2830175942Sscottl
2831169412Sscottl			hptiop_free_srb(hba, tmp_srb);
2832169412Sscottl			hba->srb[i] = tmp_srb;
2833169412Sscottl			phy_addr += HPT_SRB_MAX_SIZE;
2834169412Sscottl		}
2835169412Sscottl		else {
2836175942Sscottl			device_printf(hba->pcidev, "invalid alignment");
2837169412Sscottl			return;
2838169412Sscottl		}
2839169412Sscottl	}
2840169412Sscottl}
2841169412Sscottl
2842175942Sscottlstatic void hptiop_os_message_callback(struct hpt_iop_hba * hba, u_int32_t msg)
2843169412Sscottl{
2844242214Sdelphij	hba->msg_done = 1;
2845169412Sscottl}
2846169412Sscottl
2847175942Sscottlstatic  int hptiop_os_query_remove_device(struct hpt_iop_hba * hba,
2848175942Sscottl						int target_id)
2849169412Sscottl{
2850169412Sscottl	struct cam_periph       *periph = NULL;
2851169412Sscottl	struct cam_path         *path;
2852169412Sscottl	int                     status, retval = 0;
2853169412Sscottl
2854169412Sscottl	status = xpt_create_path(&path, NULL, hba->sim->path_id, target_id, 0);
2855169412Sscottl
2856169412Sscottl	if (status == CAM_REQ_CMP) {
2857169412Sscottl		if ((periph = cam_periph_find(path, "da")) != NULL) {
2858169412Sscottl			if (periph->refcount >= 1) {
2859175942Sscottl				device_printf(hba->pcidev, "%d ,"
2860175942Sscottl					"target_id=0x%x,"
2861175942Sscottl					"refcount=%d",
2862169412Sscottl				    hba->pciunit, target_id, periph->refcount);
2863169412Sscottl				retval = -1;
2864169412Sscottl			}
2865169412Sscottl		}
2866169412Sscottl		xpt_free_path(path);
2867169412Sscottl	}
2868169412Sscottl	return retval;
2869169412Sscottl}
2870169412Sscottl
2871169412Sscottlstatic void hptiop_release_resource(struct hpt_iop_hba *hba)
2872169412Sscottl{
2873175942Sscottl	int i;
2874175942Sscottl	if (hba->path) {
2875175942Sscottl		struct ccb_setasync ccb;
2876169412Sscottl
2877169412Sscottl		xpt_setup_ccb(&ccb.ccb_h, hba->path, /*priority*/5);
2878169412Sscottl		ccb.ccb_h.func_code = XPT_SASYNC_CB;
2879169412Sscottl		ccb.event_enable = 0;
2880169412Sscottl		ccb.callback = hptiop_async;
2881169412Sscottl		ccb.callback_arg = hba->sim;
2882169412Sscottl		xpt_action((union ccb *)&ccb);
2883169412Sscottl		xpt_free_path(hba->path);
2884169412Sscottl	}
2885169412Sscottl
2886169412Sscottl	if (hba->sim) {
2887169412Sscottl		xpt_bus_deregister(cam_sim_path(hba->sim));
2888169412Sscottl		cam_sim_free(hba->sim, TRUE);
2889169412Sscottl	}
2890169412Sscottl
2891175942Sscottl	if (hba->ctlcfg_dmat) {
2892175942Sscottl		bus_dmamap_unload(hba->ctlcfg_dmat, hba->ctlcfg_dmamap);
2893175942Sscottl		bus_dmamem_free(hba->ctlcfg_dmat,
2894175942Sscottl					hba->ctlcfg_ptr, hba->ctlcfg_dmamap);
2895175942Sscottl		bus_dma_tag_destroy(hba->ctlcfg_dmat);
2896175942Sscottl	}
2897175942Sscottl
2898175942Sscottl	for (i = 0; i < HPT_SRB_MAX_QUEUE_SIZE; i++) {
2899175942Sscottl		struct hpt_iop_srb *srb = hba->srb[i];
2900175942Sscottl		if (srb->dma_map)
2901175942Sscottl			bus_dmamap_destroy(hba->io_dmat, srb->dma_map);
2902175942Sscottl	}
2903175942Sscottl
2904169412Sscottl	if (hba->srb_dmat) {
2905169412Sscottl		bus_dmamap_unload(hba->srb_dmat, hba->srb_dmamap);
2906175942Sscottl		bus_dmamap_destroy(hba->srb_dmat, hba->srb_dmamap);
2907169412Sscottl		bus_dma_tag_destroy(hba->srb_dmat);
2908169412Sscottl	}
2909169412Sscottl
2910169412Sscottl	if (hba->io_dmat)
2911169412Sscottl		bus_dma_tag_destroy(hba->io_dmat);
2912169412Sscottl
2913169412Sscottl	if (hba->parent_dmat)
2914169412Sscottl		bus_dma_tag_destroy(hba->parent_dmat);
2915169412Sscottl
2916169412Sscottl	if (hba->irq_handle)
2917169412Sscottl		bus_teardown_intr(hba->pcidev, hba->irq_res, hba->irq_handle);
2918169412Sscottl
2919169412Sscottl	if (hba->irq_res)
2920175942Sscottl		bus_release_resource(hba->pcidev, SYS_RES_IRQ,
2921175942Sscottl					0, hba->irq_res);
2922169412Sscottl
2923169412Sscottl	if (hba->bar0_res)
2924169412Sscottl		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
2925169412Sscottl					hba->bar0_rid, hba->bar0_res);
2926175942Sscottl	if (hba->bar2_res)
2927175942Sscottl		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
2928175942Sscottl					hba->bar2_rid, hba->bar2_res);
2929169412Sscottl	if (hba->ioctl_dev)
2930169412Sscottl		destroy_dev(hba->ioctl_dev);
2931169412Sscottl}
2932