1331722Seadler/*
2175942Sscottl * HighPoint RR3xxx/4xxx RAID Driver for FreeBSD
3242086Sdelphij * 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: stable/11/sys/dev/hptiop/hptiop.c 315812 2017-03-23 06:40:20Z mav $");
29169412Sscottl
30169412Sscottl#include <sys/param.h>
31169412Sscottl#include <sys/types.h>
32169412Sscottl#include <sys/cons.h>
33169412Sscottl#include <sys/time.h>
34169412Sscottl#include <sys/systm.h>
35169412Sscottl
36169412Sscottl#include <sys/stat.h>
37169412Sscottl#include <sys/malloc.h>
38169412Sscottl#include <sys/conf.h>
39169412Sscottl#include <sys/libkern.h>
40169412Sscottl#include <sys/kernel.h>
41169412Sscottl
42169412Sscottl#include <sys/kthread.h>
43169412Sscottl#include <sys/mutex.h>
44169412Sscottl#include <sys/module.h>
45169412Sscottl
46169412Sscottl#include <sys/eventhandler.h>
47169412Sscottl#include <sys/bus.h>
48169412Sscottl#include <sys/taskqueue.h>
49169412Sscottl#include <sys/ioccom.h>
50169412Sscottl
51169412Sscottl#include <machine/resource.h>
52169412Sscottl#include <machine/bus.h>
53169412Sscottl#include <machine/stdarg.h>
54169412Sscottl#include <sys/rman.h>
55169412Sscottl
56169412Sscottl#include <vm/vm.h>
57169412Sscottl#include <vm/pmap.h>
58169412Sscottl
59169412Sscottl#include <dev/pci/pcireg.h>
60169412Sscottl#include <dev/pci/pcivar.h>
61169412Sscottl
62169412Sscottl
63169412Sscottl#include <cam/cam.h>
64169412Sscottl#include <cam/cam_ccb.h>
65169412Sscottl#include <cam/cam_sim.h>
66169412Sscottl#include <cam/cam_xpt_sim.h>
67169412Sscottl#include <cam/cam_debug.h>
68169412Sscottl#include <cam/cam_periph.h>
69169412Sscottl#include <cam/scsi/scsi_all.h>
70169412Sscottl#include <cam/scsi/scsi_message.h>
71169412Sscottl
72169412Sscottl
73169412Sscottl#include <dev/hptiop/hptiop.h>
74169412Sscottl
75242086Sdelphijstatic const char driver_name[] = "hptiop";
76252851Sdelphijstatic const char driver_version[] = "v1.9";
77169412Sscottl
78169412Sscottlstatic devclass_t hptiop_devclass;
79169412Sscottl
80175942Sscottlstatic int hptiop_send_sync_msg(struct hpt_iop_hba *hba,
81175942Sscottl				u_int32_t msg, u_int32_t millisec);
82175942Sscottlstatic void hptiop_request_callback_itl(struct hpt_iop_hba *hba,
83175942Sscottl							u_int32_t req);
84175942Sscottlstatic void hptiop_request_callback_mv(struct hpt_iop_hba *hba, u_int64_t req);
85242086Sdelphijstatic void hptiop_request_callback_mvfrey(struct hpt_iop_hba *hba,
86242086Sdelphij							u_int32_t req);
87175942Sscottlstatic void hptiop_os_message_callback(struct hpt_iop_hba *hba, u_int32_t msg);
88175942Sscottlstatic int  hptiop_do_ioctl_itl(struct hpt_iop_hba *hba,
89175942Sscottl				struct hpt_iop_ioctl_param *pParams);
90175942Sscottlstatic int  hptiop_do_ioctl_mv(struct hpt_iop_hba *hba,
91175942Sscottl				struct hpt_iop_ioctl_param *pParams);
92242086Sdelphijstatic int  hptiop_do_ioctl_mvfrey(struct hpt_iop_hba *hba,
93242086Sdelphij				struct hpt_iop_ioctl_param *pParams);
94175942Sscottlstatic int  hptiop_rescan_bus(struct hpt_iop_hba *hba);
95175942Sscottlstatic int hptiop_alloc_pci_res_itl(struct hpt_iop_hba *hba);
96175942Sscottlstatic int hptiop_alloc_pci_res_mv(struct hpt_iop_hba *hba);
97242086Sdelphijstatic int hptiop_alloc_pci_res_mvfrey(struct hpt_iop_hba *hba);
98175942Sscottlstatic int hptiop_get_config_itl(struct hpt_iop_hba *hba,
99175942Sscottl				struct hpt_iop_request_get_config *config);
100175942Sscottlstatic int hptiop_get_config_mv(struct hpt_iop_hba *hba,
101175942Sscottl				struct hpt_iop_request_get_config *config);
102242086Sdelphijstatic int hptiop_get_config_mvfrey(struct hpt_iop_hba *hba,
103242086Sdelphij				struct hpt_iop_request_get_config *config);
104175942Sscottlstatic int hptiop_set_config_itl(struct hpt_iop_hba *hba,
105175942Sscottl				struct hpt_iop_request_set_config *config);
106175942Sscottlstatic int hptiop_set_config_mv(struct hpt_iop_hba *hba,
107175942Sscottl				struct hpt_iop_request_set_config *config);
108242086Sdelphijstatic int hptiop_set_config_mvfrey(struct hpt_iop_hba *hba,
109242086Sdelphij				struct hpt_iop_request_set_config *config);
110175942Sscottlstatic int hptiop_internal_memalloc_mv(struct hpt_iop_hba *hba);
111242086Sdelphijstatic int hptiop_internal_memalloc_mvfrey(struct hpt_iop_hba *hba);
112242086Sdelphijstatic int hptiop_internal_memfree_itl(struct hpt_iop_hba *hba);
113175942Sscottlstatic int hptiop_internal_memfree_mv(struct hpt_iop_hba *hba);
114242086Sdelphijstatic int hptiop_internal_memfree_mvfrey(struct hpt_iop_hba *hba);
115175942Sscottlstatic int  hptiop_post_ioctl_command_itl(struct hpt_iop_hba *hba,
116175942Sscottl			u_int32_t req32, struct hpt_iop_ioctl_param *pParams);
117175942Sscottlstatic int  hptiop_post_ioctl_command_mv(struct hpt_iop_hba *hba,
118175942Sscottl				struct hpt_iop_request_ioctl_command *req,
119175942Sscottl				struct hpt_iop_ioctl_param *pParams);
120242086Sdelphijstatic int  hptiop_post_ioctl_command_mvfrey(struct hpt_iop_hba *hba,
121242086Sdelphij				struct hpt_iop_request_ioctl_command *req,
122242086Sdelphij				struct hpt_iop_ioctl_param *pParams);
123175942Sscottlstatic void hptiop_post_req_itl(struct hpt_iop_hba *hba,
124175942Sscottl				struct hpt_iop_srb *srb,
125175942Sscottl				bus_dma_segment_t *segs, int nsegs);
126175942Sscottlstatic void hptiop_post_req_mv(struct hpt_iop_hba *hba,
127175942Sscottl				struct hpt_iop_srb *srb,
128175942Sscottl				bus_dma_segment_t *segs, int nsegs);
129242086Sdelphijstatic void hptiop_post_req_mvfrey(struct hpt_iop_hba *hba,
130242086Sdelphij				struct hpt_iop_srb *srb,
131242086Sdelphij				bus_dma_segment_t *segs, int nsegs);
132175942Sscottlstatic void hptiop_post_msg_itl(struct hpt_iop_hba *hba, u_int32_t msg);
133175942Sscottlstatic void hptiop_post_msg_mv(struct hpt_iop_hba *hba, u_int32_t msg);
134242086Sdelphijstatic void hptiop_post_msg_mvfrey(struct hpt_iop_hba *hba, u_int32_t msg);
135175942Sscottlstatic void hptiop_enable_intr_itl(struct hpt_iop_hba *hba);
136175942Sscottlstatic void hptiop_enable_intr_mv(struct hpt_iop_hba *hba);
137242086Sdelphijstatic void hptiop_enable_intr_mvfrey(struct hpt_iop_hba *hba);
138175942Sscottlstatic void hptiop_disable_intr_itl(struct hpt_iop_hba *hba);
139175942Sscottlstatic void hptiop_disable_intr_mv(struct hpt_iop_hba *hba);
140242086Sdelphijstatic void hptiop_disable_intr_mvfrey(struct hpt_iop_hba *hba);
141175942Sscottlstatic void hptiop_free_srb(struct hpt_iop_hba *hba, struct hpt_iop_srb *srb);
142175942Sscottlstatic int  hptiop_os_query_remove_device(struct hpt_iop_hba *hba, int tid);
143169412Sscottlstatic int  hptiop_probe(device_t dev);
144169412Sscottlstatic int  hptiop_attach(device_t dev);
145169412Sscottlstatic int  hptiop_detach(device_t dev);
146169412Sscottlstatic int  hptiop_shutdown(device_t dev);
147169412Sscottlstatic void hptiop_action(struct cam_sim *sim, union ccb *ccb);
148169412Sscottlstatic void hptiop_poll(struct cam_sim *sim);
149175942Sscottlstatic void hptiop_async(void *callback_arg, u_int32_t code,
150175942Sscottl					struct cam_path *path, void *arg);
151169412Sscottlstatic void hptiop_pci_intr(void *arg);
152175942Sscottlstatic void hptiop_release_resource(struct hpt_iop_hba *hba);
153242086Sdelphijstatic void hptiop_reset_adapter(void *argv);
154169412Sscottlstatic d_open_t hptiop_open;
155169412Sscottlstatic d_close_t hptiop_close;
156169412Sscottlstatic d_ioctl_t hptiop_ioctl;
157169412Sscottl
158169412Sscottlstatic struct cdevsw hptiop_cdevsw = {
159169412Sscottl	.d_open = hptiop_open,
160169412Sscottl	.d_close = hptiop_close,
161169412Sscottl	.d_ioctl = hptiop_ioctl,
162169412Sscottl	.d_name = driver_name,
163169412Sscottl	.d_version = D_VERSION,
164169412Sscottl};
165169412Sscottl
166169412Sscottl#define hba_from_dev(dev) \
167183397Sed	((struct hpt_iop_hba *)devclass_get_softc(hptiop_devclass, dev2unit(dev)))
168169412Sscottl
169175942Sscottl#define BUS_SPACE_WRT4_ITL(offset, value) bus_space_write_4(hba->bar0t,\
170175942Sscottl		hba->bar0h, offsetof(struct hpt_iopmu_itl, offset), (value))
171175942Sscottl#define BUS_SPACE_RD4_ITL(offset) bus_space_read_4(hba->bar0t,\
172175942Sscottl		hba->bar0h, offsetof(struct hpt_iopmu_itl, offset))
173175942Sscottl
174175942Sscottl#define BUS_SPACE_WRT4_MV0(offset, value) bus_space_write_4(hba->bar0t,\
175175942Sscottl		hba->bar0h, offsetof(struct hpt_iopmv_regs, offset), value)
176175942Sscottl#define BUS_SPACE_RD4_MV0(offset) bus_space_read_4(hba->bar0t,\
177175942Sscottl		hba->bar0h, offsetof(struct hpt_iopmv_regs, offset))
178175942Sscottl#define BUS_SPACE_WRT4_MV2(offset, value) bus_space_write_4(hba->bar2t,\
179175942Sscottl		hba->bar2h, offsetof(struct hpt_iopmu_mv, offset), value)
180175942Sscottl#define BUS_SPACE_RD4_MV2(offset) bus_space_read_4(hba->bar2t,\
181175942Sscottl		hba->bar2h, offsetof(struct hpt_iopmu_mv, offset))
182175942Sscottl
183242086Sdelphij#define BUS_SPACE_WRT4_MVFREY2(offset, value) bus_space_write_4(hba->bar2t,\
184242086Sdelphij		hba->bar2h, offsetof(struct hpt_iopmu_mvfrey, offset), value)
185242086Sdelphij#define BUS_SPACE_RD4_MVFREY2(offset) bus_space_read_4(hba->bar2t,\
186242086Sdelphij		hba->bar2h, offsetof(struct hpt_iopmu_mvfrey, offset))
187242086Sdelphij
188169412Sscottlstatic int hptiop_open(ioctl_dev_t dev, int flags,
189169412Sscottl					int devtype, ioctl_thread_t proc)
190169412Sscottl{
191175942Sscottl	struct hpt_iop_hba *hba = hba_from_dev(dev);
192169412Sscottl
193169412Sscottl	if (hba==NULL)
194169412Sscottl		return ENXIO;
195169412Sscottl	if (hba->flag & HPT_IOCTL_FLAG_OPEN)
196169412Sscottl		return EBUSY;
197169412Sscottl	hba->flag |= HPT_IOCTL_FLAG_OPEN;
198169412Sscottl	return 0;
199169412Sscottl}
200169412Sscottl
201169412Sscottlstatic int hptiop_close(ioctl_dev_t dev, int flags,
202169412Sscottl					int devtype, ioctl_thread_t proc)
203169412Sscottl{
204175942Sscottl	struct hpt_iop_hba *hba = hba_from_dev(dev);
205169412Sscottl	hba->flag &= ~(u_int32_t)HPT_IOCTL_FLAG_OPEN;
206169412Sscottl	return 0;
207169412Sscottl}
208169412Sscottl
209169412Sscottlstatic int hptiop_ioctl(ioctl_dev_t dev, u_long cmd, caddr_t data,
210169412Sscottl					int flags, ioctl_thread_t proc)
211169412Sscottl{
212169412Sscottl	int ret = EFAULT;
213175942Sscottl	struct hpt_iop_hba *hba = hba_from_dev(dev);
214169412Sscottl
215169412Sscottl	mtx_lock(&Giant);
216169412Sscottl
217169412Sscottl	switch (cmd) {
218169412Sscottl	case HPT_DO_IOCONTROL:
219175942Sscottl		ret = hba->ops->do_ioctl(hba,
220175942Sscottl				(struct hpt_iop_ioctl_param *)data);
221169412Sscottl		break;
222169412Sscottl	case HPT_SCAN_BUS:
223169412Sscottl		ret = hptiop_rescan_bus(hba);
224169412Sscottl		break;
225169412Sscottl	}
226169412Sscottl
227169412Sscottl	mtx_unlock(&Giant);
228169412Sscottl
229169412Sscottl	return ret;
230169412Sscottl}
231169412Sscottl
232175942Sscottlstatic u_int64_t hptiop_mv_outbound_read(struct hpt_iop_hba *hba)
233169412Sscottl{
234175942Sscottl	u_int64_t p;
235175942Sscottl	u_int32_t outbound_tail = BUS_SPACE_RD4_MV2(outbound_tail);
236175942Sscottl	u_int32_t outbound_head = BUS_SPACE_RD4_MV2(outbound_head);
237175942Sscottl
238175942Sscottl	if (outbound_tail != outbound_head) {
239175942Sscottl		bus_space_read_region_4(hba->bar2t, hba->bar2h,
240175942Sscottl			offsetof(struct hpt_iopmu_mv,
241175942Sscottl				outbound_q[outbound_tail]),
242175942Sscottl			(u_int32_t *)&p, 2);
243175942Sscottl
244175942Sscottl		outbound_tail++;
245175942Sscottl
246175942Sscottl		if (outbound_tail == MVIOP_QUEUE_LEN)
247175942Sscottl			outbound_tail = 0;
248175942Sscottl
249175942Sscottl		BUS_SPACE_WRT4_MV2(outbound_tail, outbound_tail);
250175942Sscottl		return p;
251175942Sscottl	} else
252175942Sscottl		return 0;
253169412Sscottl}
254169412Sscottl
255175942Sscottlstatic void hptiop_mv_inbound_write(u_int64_t p, struct hpt_iop_hba *hba)
256169412Sscottl{
257175942Sscottl	u_int32_t inbound_head = BUS_SPACE_RD4_MV2(inbound_head);
258175942Sscottl	u_int32_t head = inbound_head + 1;
259175942Sscottl
260175942Sscottl	if (head == MVIOP_QUEUE_LEN)
261175942Sscottl		head = 0;
262175942Sscottl
263175942Sscottl	bus_space_write_region_4(hba->bar2t, hba->bar2h,
264175942Sscottl			offsetof(struct hpt_iopmu_mv, inbound_q[inbound_head]),
265175942Sscottl			(u_int32_t *)&p, 2);
266175942Sscottl	BUS_SPACE_WRT4_MV2(inbound_head, head);
267175942Sscottl	BUS_SPACE_WRT4_MV0(inbound_doorbell, MVIOP_MU_INBOUND_INT_POSTQUEUE);
268169412Sscottl}
269169412Sscottl
270175942Sscottlstatic void hptiop_post_msg_itl(struct hpt_iop_hba *hba, u_int32_t msg)
271169412Sscottl{
272175942Sscottl	BUS_SPACE_WRT4_ITL(inbound_msgaddr0, msg);
273175942Sscottl	BUS_SPACE_RD4_ITL(outbound_intstatus);
274169412Sscottl}
275169412Sscottl
276175942Sscottlstatic void hptiop_post_msg_mv(struct hpt_iop_hba *hba, u_int32_t msg)
277169412Sscottl{
278175942Sscottl
279175942Sscottl	BUS_SPACE_WRT4_MV2(inbound_msg, msg);
280175942Sscottl	BUS_SPACE_WRT4_MV0(inbound_doorbell, MVIOP_MU_INBOUND_INT_MSG);
281175942Sscottl
282175942Sscottl	BUS_SPACE_RD4_MV0(outbound_intmask);
283169412Sscottl}
284169412Sscottl
285242086Sdelphijstatic void hptiop_post_msg_mvfrey(struct hpt_iop_hba *hba, u_int32_t msg)
286242086Sdelphij{
287242086Sdelphij	BUS_SPACE_WRT4_MVFREY2(f0_to_cpu_msg_a, msg);
288242086Sdelphij	BUS_SPACE_RD4_MVFREY2(f0_to_cpu_msg_a);
289242086Sdelphij}
290242086Sdelphij
291175942Sscottlstatic int hptiop_wait_ready_itl(struct hpt_iop_hba * hba, u_int32_t millisec)
292169412Sscottl{
293169412Sscottl	u_int32_t req=0;
294169412Sscottl	int i;
295169412Sscottl
296169412Sscottl	for (i = 0; i < millisec; i++) {
297175942Sscottl		req = BUS_SPACE_RD4_ITL(inbound_queue);
298169412Sscottl		if (req != IOPMU_QUEUE_EMPTY)
299169412Sscottl			break;
300169412Sscottl		DELAY(1000);
301169412Sscottl	}
302169412Sscottl
303169412Sscottl	if (req!=IOPMU_QUEUE_EMPTY) {
304175942Sscottl		BUS_SPACE_WRT4_ITL(outbound_queue, req);
305175942Sscottl		BUS_SPACE_RD4_ITL(outbound_intstatus);
306169412Sscottl		return 0;
307169412Sscottl	}
308169412Sscottl
309169412Sscottl	return -1;
310169412Sscottl}
311169412Sscottl
312175942Sscottlstatic int hptiop_wait_ready_mv(struct hpt_iop_hba * hba, u_int32_t millisec)
313169412Sscottl{
314175942Sscottl	if (hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_NOP, millisec))
315175942Sscottl		return -1;
316175942Sscottl
317175942Sscottl	return 0;
318175942Sscottl}
319175942Sscottl
320242086Sdelphijstatic int hptiop_wait_ready_mvfrey(struct hpt_iop_hba * hba,
321242086Sdelphij							u_int32_t millisec)
322242086Sdelphij{
323242086Sdelphij	if (hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_NOP, millisec))
324242086Sdelphij		return -1;
325242086Sdelphij
326242086Sdelphij	return 0;
327242086Sdelphij}
328242086Sdelphij
329175942Sscottlstatic void hptiop_request_callback_itl(struct hpt_iop_hba * hba,
330175942Sscottl							u_int32_t index)
331175942Sscottl{
332175942Sscottl	struct hpt_iop_srb *srb;
333315221Spfg	struct hpt_iop_request_scsi_command *req=NULL;
334175942Sscottl	union ccb *ccb;
335175942Sscottl	u_int8_t *cdb;
336175942Sscottl	u_int32_t result, temp, dxfer;
337175942Sscottl	u_int64_t temp64;
338175942Sscottl
339175942Sscottl	if (index & IOPMU_QUEUE_MASK_HOST_BITS) { /*host req*/
340175942Sscottl		if (hba->firmware_version > 0x01020000 ||
341175942Sscottl			hba->interface_version > 0x01020000) {
342175942Sscottl			srb = hba->srb[index & ~(u_int32_t)
343175942Sscottl				(IOPMU_QUEUE_ADDR_HOST_BIT
344175942Sscottl				| IOPMU_QUEUE_REQUEST_RESULT_BIT)];
345175942Sscottl			req = (struct hpt_iop_request_scsi_command *)srb;
346175942Sscottl			if (index & IOPMU_QUEUE_REQUEST_RESULT_BIT)
347175942Sscottl				result = IOP_RESULT_SUCCESS;
348175942Sscottl			else
349175942Sscottl				result = req->header.result;
350175942Sscottl		} else {
351175942Sscottl			srb = hba->srb[index &
352175942Sscottl				~(u_int32_t)IOPMU_QUEUE_ADDR_HOST_BIT];
353175942Sscottl			req = (struct hpt_iop_request_scsi_command *)srb;
354175942Sscottl			result = req->header.result;
355175942Sscottl		}
356175942Sscottl		dxfer = req->dataxfer_length;
357175942Sscottl		goto srb_complete;
358175942Sscottl	}
359175942Sscottl
360175942Sscottl	/*iop req*/
361175942Sscottl	temp = bus_space_read_4(hba->bar0t, hba->bar0h, index +
362175942Sscottl		offsetof(struct hpt_iop_request_header, type));
363175942Sscottl	result = bus_space_read_4(hba->bar0t, hba->bar0h, index +
364175942Sscottl		offsetof(struct hpt_iop_request_header, result));
365175942Sscottl	switch(temp) {
366175942Sscottl	case IOP_REQUEST_TYPE_IOCTL_COMMAND:
367175942Sscottl	{
368175942Sscottl		temp64 = 0;
369175942Sscottl		bus_space_write_region_4(hba->bar0t, hba->bar0h, index +
370175942Sscottl			offsetof(struct hpt_iop_request_header, context),
371175942Sscottl			(u_int32_t *)&temp64, 2);
372175942Sscottl		wakeup((void *)((unsigned long)hba->u.itl.mu + index));
373175942Sscottl		break;
374175942Sscottl	}
375175942Sscottl
376175942Sscottl	case IOP_REQUEST_TYPE_SCSI_COMMAND:
377175942Sscottl		bus_space_read_region_4(hba->bar0t, hba->bar0h, index +
378175942Sscottl			offsetof(struct hpt_iop_request_header, context),
379175942Sscottl			(u_int32_t *)&temp64, 2);
380175942Sscottl		srb = (struct hpt_iop_srb *)(unsigned long)temp64;
381175942Sscottl		dxfer = bus_space_read_4(hba->bar0t, hba->bar0h,
382175942Sscottl				index + offsetof(struct hpt_iop_request_scsi_command,
383175942Sscottl				dataxfer_length));
384175942Sscottlsrb_complete:
385175942Sscottl		ccb = (union ccb *)srb->ccb;
386175942Sscottl		if (ccb->ccb_h.flags & CAM_CDB_POINTER)
387175942Sscottl			cdb = ccb->csio.cdb_io.cdb_ptr;
388175942Sscottl		else
389175942Sscottl			cdb = ccb->csio.cdb_io.cdb_bytes;
390175942Sscottl
391175942Sscottl		if (cdb[0] == SYNCHRONIZE_CACHE) { /* ??? */
392175942Sscottl			ccb->ccb_h.status = CAM_REQ_CMP;
393175942Sscottl			goto scsi_done;
394175942Sscottl		}
395175942Sscottl
396175942Sscottl		switch (result) {
397175942Sscottl		case IOP_RESULT_SUCCESS:
398175942Sscottl			switch (ccb->ccb_h.flags & CAM_DIR_MASK) {
399175942Sscottl			case CAM_DIR_IN:
400175942Sscottl				bus_dmamap_sync(hba->io_dmat,
401175942Sscottl					srb->dma_map, BUS_DMASYNC_POSTREAD);
402175942Sscottl				bus_dmamap_unload(hba->io_dmat, srb->dma_map);
403175942Sscottl				break;
404175942Sscottl			case CAM_DIR_OUT:
405175942Sscottl				bus_dmamap_sync(hba->io_dmat,
406175942Sscottl					srb->dma_map, BUS_DMASYNC_POSTWRITE);
407175942Sscottl				bus_dmamap_unload(hba->io_dmat, srb->dma_map);
408175942Sscottl				break;
409175942Sscottl			}
410175942Sscottl
411175942Sscottl			ccb->ccb_h.status = CAM_REQ_CMP;
412175942Sscottl			break;
413175942Sscottl
414175942Sscottl		case IOP_RESULT_BAD_TARGET:
415175942Sscottl			ccb->ccb_h.status = CAM_DEV_NOT_THERE;
416175942Sscottl			break;
417175942Sscottl		case IOP_RESULT_BUSY:
418175942Sscottl			ccb->ccb_h.status = CAM_BUSY;
419175942Sscottl			break;
420175942Sscottl		case IOP_RESULT_INVALID_REQUEST:
421175942Sscottl			ccb->ccb_h.status = CAM_REQ_INVALID;
422175942Sscottl			break;
423175942Sscottl		case IOP_RESULT_FAIL:
424175942Sscottl			ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
425175942Sscottl			break;
426175942Sscottl		case IOP_RESULT_RESET:
427175942Sscottl			ccb->ccb_h.status = CAM_BUSY;
428175942Sscottl			break;
429175942Sscottl		case IOP_RESULT_CHECK_CONDITION:
430226350Smarius			memset(&ccb->csio.sense_data, 0,
431226350Smarius			    sizeof(ccb->csio.sense_data));
432226350Smarius			if (dxfer < ccb->csio.sense_len)
433226350Smarius				ccb->csio.sense_resid = ccb->csio.sense_len -
434226350Smarius				    dxfer;
435226350Smarius			else
436226350Smarius				ccb->csio.sense_resid = 0;
437175942Sscottl			if (srb->srb_flag & HPT_SRB_FLAG_HIGH_MEM_ACESS) {/*iop*/
438175942Sscottl				bus_space_read_region_1(hba->bar0t, hba->bar0h,
439175942Sscottl					index + offsetof(struct hpt_iop_request_scsi_command,
440175942Sscottl					sg_list), (u_int8_t *)&ccb->csio.sense_data,
441175942Sscottl					MIN(dxfer, sizeof(ccb->csio.sense_data)));
442175942Sscottl			} else {
443175942Sscottl				memcpy(&ccb->csio.sense_data, &req->sg_list,
444175942Sscottl					MIN(dxfer, sizeof(ccb->csio.sense_data)));
445175942Sscottl			}
446175942Sscottl			ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
447175942Sscottl			ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
448175942Sscottl			ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
449175942Sscottl			break;
450175942Sscottl		default:
451175942Sscottl			ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
452175942Sscottl			break;
453175942Sscottl		}
454175942Sscottlscsi_done:
455175942Sscottl		if (srb->srb_flag & HPT_SRB_FLAG_HIGH_MEM_ACESS)
456175942Sscottl			BUS_SPACE_WRT4_ITL(outbound_queue, index);
457175942Sscottl
458175942Sscottl		ccb->csio.resid = ccb->csio.dxfer_len - dxfer;
459175942Sscottl
460175942Sscottl		hptiop_free_srb(hba, srb);
461175942Sscottl		xpt_done(ccb);
462175942Sscottl		break;
463175942Sscottl	}
464175942Sscottl}
465175942Sscottl
466175942Sscottlstatic void hptiop_drain_outbound_queue_itl(struct hpt_iop_hba *hba)
467175942Sscottl{
468175942Sscottl	u_int32_t req, temp;
469175942Sscottl
470175942Sscottl	while ((req = BUS_SPACE_RD4_ITL(outbound_queue)) !=IOPMU_QUEUE_EMPTY) {
471175942Sscottl		if (req & IOPMU_QUEUE_MASK_HOST_BITS)
472175942Sscottl			hptiop_request_callback_itl(hba, req);
473175942Sscottl		else {
474175942Sscottl			struct hpt_iop_request_header *p;
475175942Sscottl
476175942Sscottl			p = (struct hpt_iop_request_header *)
477175942Sscottl				((char *)hba->u.itl.mu + req);
478175942Sscottl			temp = bus_space_read_4(hba->bar0t,
479175942Sscottl					hba->bar0h,req +
480175942Sscottl					offsetof(struct hpt_iop_request_header,
481175942Sscottl						flags));
482175942Sscottl			if (temp & IOP_REQUEST_FLAG_SYNC_REQUEST) {
483175942Sscottl				u_int64_t temp64;
484175942Sscottl				bus_space_read_region_4(hba->bar0t,
485175942Sscottl					hba->bar0h,req +
486175942Sscottl					offsetof(struct hpt_iop_request_header,
487175942Sscottl						context),
488175942Sscottl					(u_int32_t *)&temp64, 2);
489175942Sscottl				if (temp64) {
490175942Sscottl					hptiop_request_callback_itl(hba, req);
491175942Sscottl				} else {
492175942Sscottl					temp64 = 1;
493175942Sscottl					bus_space_write_region_4(hba->bar0t,
494175942Sscottl						hba->bar0h,req +
495175942Sscottl						offsetof(struct hpt_iop_request_header,
496175942Sscottl							context),
497175942Sscottl						(u_int32_t *)&temp64, 2);
498175942Sscottl				}
499175942Sscottl			} else
500175942Sscottl				hptiop_request_callback_itl(hba, req);
501175942Sscottl		}
502175942Sscottl	}
503175942Sscottl}
504175942Sscottl
505175942Sscottlstatic int hptiop_intr_itl(struct hpt_iop_hba * hba)
506175942Sscottl{
507169412Sscottl	u_int32_t status;
508169412Sscottl	int ret = 0;
509169412Sscottl
510175942Sscottl	status = BUS_SPACE_RD4_ITL(outbound_intstatus);
511169412Sscottl
512169412Sscottl	if (status & IOPMU_OUTBOUND_INT_MSG0) {
513175942Sscottl		u_int32_t msg = BUS_SPACE_RD4_ITL(outbound_msgaddr0);
514175942Sscottl		KdPrint(("hptiop: received outbound msg %x\n", msg));
515175942Sscottl		BUS_SPACE_WRT4_ITL(outbound_intstatus, IOPMU_OUTBOUND_INT_MSG0);
516175942Sscottl		hptiop_os_message_callback(hba, msg);
517169412Sscottl		ret = 1;
518169412Sscottl	}
519169412Sscottl
520169412Sscottl	if (status & IOPMU_OUTBOUND_INT_POSTQUEUE) {
521175942Sscottl		hptiop_drain_outbound_queue_itl(hba);
522175942Sscottl		ret = 1;
523175942Sscottl	}
524175942Sscottl
525175942Sscottl	return ret;
526175942Sscottl}
527175942Sscottl
528175942Sscottlstatic void hptiop_request_callback_mv(struct hpt_iop_hba * hba,
529175942Sscottl							u_int64_t _tag)
530175942Sscottl{
531175942Sscottl	u_int32_t context = (u_int32_t)_tag;
532175942Sscottl
533175942Sscottl	if (context & MVIOP_CMD_TYPE_SCSI) {
534175942Sscottl		struct hpt_iop_srb *srb;
535175942Sscottl		struct hpt_iop_request_scsi_command *req;
536175942Sscottl		union ccb *ccb;
537175942Sscottl		u_int8_t *cdb;
538175942Sscottl
539175942Sscottl		srb = hba->srb[context >> MVIOP_REQUEST_NUMBER_START_BIT];
540175942Sscottl		req = (struct hpt_iop_request_scsi_command *)srb;
541175942Sscottl		ccb = (union ccb *)srb->ccb;
542175942Sscottl		if (ccb->ccb_h.flags & CAM_CDB_POINTER)
543175942Sscottl			cdb = ccb->csio.cdb_io.cdb_ptr;
544175942Sscottl		else
545175942Sscottl			cdb = ccb->csio.cdb_io.cdb_bytes;
546175942Sscottl
547175942Sscottl		if (cdb[0] == SYNCHRONIZE_CACHE) { /* ??? */
548175942Sscottl			ccb->ccb_h.status = CAM_REQ_CMP;
549175942Sscottl			goto scsi_done;
550175942Sscottl		}
551175942Sscottl		if (context & MVIOP_MU_QUEUE_REQUEST_RESULT_BIT)
552175942Sscottl			req->header.result = IOP_RESULT_SUCCESS;
553175942Sscottl
554175942Sscottl		switch (req->header.result) {
555175942Sscottl		case IOP_RESULT_SUCCESS:
556175942Sscottl			switch (ccb->ccb_h.flags & CAM_DIR_MASK) {
557175942Sscottl			case CAM_DIR_IN:
558175942Sscottl				bus_dmamap_sync(hba->io_dmat,
559175942Sscottl					srb->dma_map, BUS_DMASYNC_POSTREAD);
560175942Sscottl				bus_dmamap_unload(hba->io_dmat, srb->dma_map);
561175942Sscottl				break;
562175942Sscottl			case CAM_DIR_OUT:
563175942Sscottl				bus_dmamap_sync(hba->io_dmat,
564175942Sscottl					srb->dma_map, BUS_DMASYNC_POSTWRITE);
565175942Sscottl				bus_dmamap_unload(hba->io_dmat, srb->dma_map);
566175942Sscottl				break;
567169412Sscottl			}
568175942Sscottl			ccb->ccb_h.status = CAM_REQ_CMP;
569175942Sscottl			break;
570175942Sscottl		case IOP_RESULT_BAD_TARGET:
571175942Sscottl			ccb->ccb_h.status = CAM_DEV_NOT_THERE;
572175942Sscottl			break;
573175942Sscottl		case IOP_RESULT_BUSY:
574175942Sscottl			ccb->ccb_h.status = CAM_BUSY;
575175942Sscottl			break;
576175942Sscottl		case IOP_RESULT_INVALID_REQUEST:
577175942Sscottl			ccb->ccb_h.status = CAM_REQ_INVALID;
578175942Sscottl			break;
579175942Sscottl		case IOP_RESULT_FAIL:
580175942Sscottl			ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
581175942Sscottl			break;
582175942Sscottl		case IOP_RESULT_RESET:
583175942Sscottl			ccb->ccb_h.status = CAM_BUSY;
584175942Sscottl			break;
585175942Sscottl		case IOP_RESULT_CHECK_CONDITION:
586226350Smarius			memset(&ccb->csio.sense_data, 0,
587226350Smarius			    sizeof(ccb->csio.sense_data));
588226350Smarius			if (req->dataxfer_length < ccb->csio.sense_len)
589226350Smarius				ccb->csio.sense_resid = ccb->csio.sense_len -
590226350Smarius				    req->dataxfer_length;
591226350Smarius			else
592226350Smarius				ccb->csio.sense_resid = 0;
593175942Sscottl			memcpy(&ccb->csio.sense_data, &req->sg_list,
594175942Sscottl				MIN(req->dataxfer_length, sizeof(ccb->csio.sense_data)));
595175942Sscottl			ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
596175942Sscottl			ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
597175942Sscottl			ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
598175942Sscottl			break;
599175942Sscottl		default:
600175942Sscottl			ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
601175942Sscottl			break;
602169412Sscottl		}
603175942Sscottlscsi_done:
604175942Sscottl		ccb->csio.resid = ccb->csio.dxfer_len - req->dataxfer_length;
605175942Sscottl
606175942Sscottl		hptiop_free_srb(hba, srb);
607175942Sscottl		xpt_done(ccb);
608175942Sscottl	} else if (context & MVIOP_CMD_TYPE_IOCTL) {
609175942Sscottl		struct hpt_iop_request_ioctl_command *req = hba->ctlcfg_ptr;
610175942Sscottl		if (context & MVIOP_MU_QUEUE_REQUEST_RESULT_BIT)
611175942Sscottl			hba->config_done = 1;
612175942Sscottl		else
613175942Sscottl			hba->config_done = -1;
614175942Sscottl		wakeup(req);
615175942Sscottl	} else if (context &
616175942Sscottl			(MVIOP_CMD_TYPE_SET_CONFIG |
617175942Sscottl				MVIOP_CMD_TYPE_GET_CONFIG))
618175942Sscottl		hba->config_done = 1;
619175942Sscottl	else {
620175942Sscottl		device_printf(hba->pcidev, "wrong callback type\n");
621175942Sscottl	}
622175942Sscottl}
623175942Sscottl
624242086Sdelphijstatic void hptiop_request_callback_mvfrey(struct hpt_iop_hba * hba,
625242086Sdelphij				u_int32_t _tag)
626242086Sdelphij{
627242086Sdelphij	u_int32_t req_type = _tag & 0xf;
628242086Sdelphij
629242086Sdelphij	struct hpt_iop_srb *srb;
630242086Sdelphij	struct hpt_iop_request_scsi_command *req;
631242086Sdelphij	union ccb *ccb;
632242086Sdelphij	u_int8_t *cdb;
633242086Sdelphij
634242086Sdelphij	switch (req_type) {
635242086Sdelphij	case IOP_REQUEST_TYPE_GET_CONFIG:
636242086Sdelphij	case IOP_REQUEST_TYPE_SET_CONFIG:
637242086Sdelphij		hba->config_done = 1;
638242086Sdelphij		break;
639242086Sdelphij
640242086Sdelphij	case IOP_REQUEST_TYPE_SCSI_COMMAND:
641242086Sdelphij		srb = hba->srb[(_tag >> 4) & 0xff];
642242086Sdelphij		req = (struct hpt_iop_request_scsi_command *)srb;
643242086Sdelphij
644242086Sdelphij		ccb = (union ccb *)srb->ccb;
645242086Sdelphij
646269612Sjhb		callout_stop(&srb->timeout);
647242086Sdelphij
648242086Sdelphij		if (ccb->ccb_h.flags & CAM_CDB_POINTER)
649242086Sdelphij			cdb = ccb->csio.cdb_io.cdb_ptr;
650242086Sdelphij		else
651242086Sdelphij			cdb = ccb->csio.cdb_io.cdb_bytes;
652242086Sdelphij
653242086Sdelphij		if (cdb[0] == SYNCHRONIZE_CACHE) { /* ??? */
654242086Sdelphij			ccb->ccb_h.status = CAM_REQ_CMP;
655242086Sdelphij			goto scsi_done;
656242086Sdelphij		}
657242086Sdelphij
658242086Sdelphij		if (_tag & MVFREYIOPMU_QUEUE_REQUEST_RESULT_BIT)
659242086Sdelphij			req->header.result = IOP_RESULT_SUCCESS;
660242086Sdelphij
661242086Sdelphij		switch (req->header.result) {
662242086Sdelphij		case IOP_RESULT_SUCCESS:
663242086Sdelphij			switch (ccb->ccb_h.flags & CAM_DIR_MASK) {
664242086Sdelphij			case CAM_DIR_IN:
665242086Sdelphij				bus_dmamap_sync(hba->io_dmat,
666242086Sdelphij						srb->dma_map, BUS_DMASYNC_POSTREAD);
667242086Sdelphij				bus_dmamap_unload(hba->io_dmat, srb->dma_map);
668242086Sdelphij				break;
669242086Sdelphij			case CAM_DIR_OUT:
670242086Sdelphij				bus_dmamap_sync(hba->io_dmat,
671242086Sdelphij						srb->dma_map, BUS_DMASYNC_POSTWRITE);
672242086Sdelphij				bus_dmamap_unload(hba->io_dmat, srb->dma_map);
673242086Sdelphij				break;
674242086Sdelphij			}
675242086Sdelphij			ccb->ccb_h.status = CAM_REQ_CMP;
676242086Sdelphij			break;
677242086Sdelphij		case IOP_RESULT_BAD_TARGET:
678242086Sdelphij			ccb->ccb_h.status = CAM_DEV_NOT_THERE;
679242086Sdelphij			break;
680242086Sdelphij		case IOP_RESULT_BUSY:
681242086Sdelphij			ccb->ccb_h.status = CAM_BUSY;
682242086Sdelphij			break;
683242086Sdelphij		case IOP_RESULT_INVALID_REQUEST:
684242086Sdelphij			ccb->ccb_h.status = CAM_REQ_INVALID;
685242086Sdelphij			break;
686242086Sdelphij		case IOP_RESULT_FAIL:
687242086Sdelphij			ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
688242086Sdelphij			break;
689242086Sdelphij		case IOP_RESULT_RESET:
690242086Sdelphij			ccb->ccb_h.status = CAM_BUSY;
691242086Sdelphij			break;
692242086Sdelphij		case IOP_RESULT_CHECK_CONDITION:
693242086Sdelphij			memset(&ccb->csio.sense_data, 0,
694242086Sdelphij			       sizeof(ccb->csio.sense_data));
695242086Sdelphij			if (req->dataxfer_length < ccb->csio.sense_len)
696242086Sdelphij				ccb->csio.sense_resid = ccb->csio.sense_len -
697242086Sdelphij				req->dataxfer_length;
698242086Sdelphij			else
699242086Sdelphij				ccb->csio.sense_resid = 0;
700242086Sdelphij			memcpy(&ccb->csio.sense_data, &req->sg_list,
701242086Sdelphij			       MIN(req->dataxfer_length, sizeof(ccb->csio.sense_data)));
702242086Sdelphij			ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
703242086Sdelphij			ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
704242086Sdelphij			ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
705242086Sdelphij			break;
706242086Sdelphij		default:
707242086Sdelphij			ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
708242086Sdelphij			break;
709242086Sdelphij		}
710242086Sdelphijscsi_done:
711242086Sdelphij		ccb->csio.resid = ccb->csio.dxfer_len - req->dataxfer_length;
712242086Sdelphij
713242086Sdelphij		hptiop_free_srb(hba, srb);
714242086Sdelphij		xpt_done(ccb);
715242086Sdelphij		break;
716242086Sdelphij	case IOP_REQUEST_TYPE_IOCTL_COMMAND:
717242086Sdelphij		if (_tag & MVFREYIOPMU_QUEUE_REQUEST_RESULT_BIT)
718242086Sdelphij			hba->config_done = 1;
719242086Sdelphij		else
720242086Sdelphij			hba->config_done = -1;
721242086Sdelphij		wakeup((struct hpt_iop_request_ioctl_command *)hba->ctlcfg_ptr);
722242086Sdelphij		break;
723242086Sdelphij	default:
724242086Sdelphij		device_printf(hba->pcidev, "wrong callback type\n");
725242086Sdelphij		break;
726242086Sdelphij	}
727242086Sdelphij}
728242086Sdelphij
729175942Sscottlstatic void hptiop_drain_outbound_queue_mv(struct hpt_iop_hba * hba)
730175942Sscottl{
731175942Sscottl	u_int64_t req;
732175942Sscottl
733175942Sscottl	while ((req = hptiop_mv_outbound_read(hba))) {
734175942Sscottl		if (req & MVIOP_MU_QUEUE_ADDR_HOST_BIT) {
735175942Sscottl			if (req & MVIOP_MU_QUEUE_REQUEST_RETURN_CONTEXT) {
736175942Sscottl				hptiop_request_callback_mv(hba, req);
737175942Sscottl			}
738175942Sscottl	    	}
739175942Sscottl	}
740175942Sscottl}
741175942Sscottl
742175942Sscottlstatic int hptiop_intr_mv(struct hpt_iop_hba * hba)
743175942Sscottl{
744175942Sscottl	u_int32_t status;
745175942Sscottl	int ret = 0;
746175942Sscottl
747175942Sscottl	status = BUS_SPACE_RD4_MV0(outbound_doorbell);
748175942Sscottl
749175942Sscottl	if (status)
750175942Sscottl		BUS_SPACE_WRT4_MV0(outbound_doorbell, ~status);
751175942Sscottl
752175942Sscottl	if (status & MVIOP_MU_OUTBOUND_INT_MSG) {
753175942Sscottl		u_int32_t msg = BUS_SPACE_RD4_MV2(outbound_msg);
754175942Sscottl		KdPrint(("hptiop: received outbound msg %x\n", msg));
755175942Sscottl		hptiop_os_message_callback(hba, msg);
756169412Sscottl		ret = 1;
757169412Sscottl	}
758175942Sscottl
759175942Sscottl	if (status & MVIOP_MU_OUTBOUND_INT_POSTQUEUE) {
760175942Sscottl		hptiop_drain_outbound_queue_mv(hba);
761175942Sscottl		ret = 1;
762175942Sscottl	}
763175942Sscottl
764169412Sscottl	return ret;
765169412Sscottl}
766169412Sscottl
767242086Sdelphijstatic int hptiop_intr_mvfrey(struct hpt_iop_hba * hba)
768242086Sdelphij{
769242086Sdelphij	u_int32_t status, _tag, cptr;
770242086Sdelphij	int ret = 0;
771242086Sdelphij
772242086Sdelphij	if (hba->initialized) {
773242086Sdelphij		BUS_SPACE_WRT4_MVFREY2(pcie_f0_int_enable, 0);
774242086Sdelphij	}
775242086Sdelphij
776242086Sdelphij	status = BUS_SPACE_RD4_MVFREY2(f0_doorbell);
777242086Sdelphij	if (status) {
778242086Sdelphij		BUS_SPACE_WRT4_MVFREY2(f0_doorbell, status);
779242086Sdelphij		if (status & CPU_TO_F0_DRBL_MSG_A_BIT) {
780242086Sdelphij			u_int32_t msg = BUS_SPACE_RD4_MVFREY2(cpu_to_f0_msg_a);
781242086Sdelphij			hptiop_os_message_callback(hba, msg);
782242086Sdelphij		}
783242086Sdelphij		ret = 1;
784242086Sdelphij	}
785242086Sdelphij
786242086Sdelphij	status = BUS_SPACE_RD4_MVFREY2(isr_cause);
787242086Sdelphij	if (status) {
788242086Sdelphij		BUS_SPACE_WRT4_MVFREY2(isr_cause, status);
789242086Sdelphij		do {
790242086Sdelphij			cptr = *hba->u.mvfrey.outlist_cptr & 0xff;
791242086Sdelphij			while (hba->u.mvfrey.outlist_rptr != cptr) {
792242086Sdelphij				hba->u.mvfrey.outlist_rptr++;
793242086Sdelphij				if (hba->u.mvfrey.outlist_rptr == hba->u.mvfrey.list_count) {
794242086Sdelphij					hba->u.mvfrey.outlist_rptr = 0;
795242086Sdelphij				}
796242086Sdelphij
797242086Sdelphij				_tag = hba->u.mvfrey.outlist[hba->u.mvfrey.outlist_rptr].val;
798242086Sdelphij				hptiop_request_callback_mvfrey(hba, _tag);
799242086Sdelphij				ret = 2;
800242086Sdelphij			}
801242086Sdelphij		} while (cptr != (*hba->u.mvfrey.outlist_cptr & 0xff));
802242086Sdelphij	}
803242086Sdelphij
804242086Sdelphij	if (hba->initialized) {
805242086Sdelphij		BUS_SPACE_WRT4_MVFREY2(pcie_f0_int_enable, 0x1010);
806242086Sdelphij	}
807242086Sdelphij
808242086Sdelphij	return ret;
809242086Sdelphij}
810242086Sdelphij
811175942Sscottlstatic int hptiop_send_sync_request_itl(struct hpt_iop_hba * hba,
812175942Sscottl					u_int32_t req32, u_int32_t millisec)
813169412Sscottl{
814169412Sscottl	u_int32_t i;
815175942Sscottl	u_int64_t temp64;
816169412Sscottl
817175942Sscottl	BUS_SPACE_WRT4_ITL(inbound_queue, req32);
818175942Sscottl	BUS_SPACE_RD4_ITL(outbound_intstatus);
819169412Sscottl
820169412Sscottl	for (i = 0; i < millisec; i++) {
821175942Sscottl		hptiop_intr_itl(hba);
822175942Sscottl		bus_space_read_region_4(hba->bar0t, hba->bar0h, req32 +
823175942Sscottl			offsetof(struct hpt_iop_request_header, context),
824175942Sscottl			(u_int32_t *)&temp64, 2);
825175942Sscottl		if (temp64)
826169412Sscottl			return 0;
827169412Sscottl		DELAY(1000);
828169412Sscottl	}
829169412Sscottl
830169412Sscottl	return -1;
831169412Sscottl}
832169412Sscottl
833175942Sscottlstatic int hptiop_send_sync_request_mv(struct hpt_iop_hba *hba,
834175942Sscottl					void *req, u_int32_t millisec)
835169412Sscottl{
836169412Sscottl	u_int32_t i;
837175942Sscottl	u_int64_t phy_addr;
838175942Sscottl	hba->config_done = 0;
839169412Sscottl
840175942Sscottl	phy_addr = hba->ctlcfgcmd_phy |
841175942Sscottl			(u_int64_t)MVIOP_MU_QUEUE_ADDR_HOST_BIT;
842175942Sscottl	((struct hpt_iop_request_get_config *)req)->header.flags |=
843175942Sscottl		IOP_REQUEST_FLAG_SYNC_REQUEST |
844175942Sscottl		IOP_REQUEST_FLAG_OUTPUT_CONTEXT;
845175942Sscottl	hptiop_mv_inbound_write(phy_addr, hba);
846175942Sscottl	BUS_SPACE_RD4_MV0(outbound_intmask);
847169412Sscottl
848175942Sscottl	for (i = 0; i < millisec; i++) {
849175942Sscottl		hptiop_intr_mv(hba);
850175942Sscottl		if (hba->config_done)
851175942Sscottl			return 0;
852175942Sscottl		DELAY(1000);
853175942Sscottl	}
854175942Sscottl	return -1;
855175942Sscottl}
856169412Sscottl
857242086Sdelphijstatic int hptiop_send_sync_request_mvfrey(struct hpt_iop_hba *hba,
858242086Sdelphij					void *req, u_int32_t millisec)
859242086Sdelphij{
860242086Sdelphij	u_int32_t i, index;
861242086Sdelphij	u_int64_t phy_addr;
862242086Sdelphij	struct hpt_iop_request_header *reqhdr =
863242086Sdelphij										(struct hpt_iop_request_header *)req;
864242086Sdelphij
865242086Sdelphij	hba->config_done = 0;
866242086Sdelphij
867242086Sdelphij	phy_addr = hba->ctlcfgcmd_phy;
868242086Sdelphij	reqhdr->flags = IOP_REQUEST_FLAG_SYNC_REQUEST
869242086Sdelphij					| IOP_REQUEST_FLAG_OUTPUT_CONTEXT
870242086Sdelphij					| IOP_REQUEST_FLAG_ADDR_BITS
871242086Sdelphij					| ((phy_addr >> 16) & 0xffff0000);
872242086Sdelphij	reqhdr->context = ((phy_addr & 0xffffffff) << 32 )
873242086Sdelphij					| IOPMU_QUEUE_ADDR_HOST_BIT | reqhdr->type;
874242086Sdelphij
875242086Sdelphij	hba->u.mvfrey.inlist_wptr++;
876242086Sdelphij	index = hba->u.mvfrey.inlist_wptr & 0x3fff;
877242086Sdelphij
878242086Sdelphij	if (index == hba->u.mvfrey.list_count) {
879242086Sdelphij		index = 0;
880242086Sdelphij		hba->u.mvfrey.inlist_wptr &= ~0x3fff;
881242086Sdelphij		hba->u.mvfrey.inlist_wptr ^= CL_POINTER_TOGGLE;
882242086Sdelphij	}
883242086Sdelphij
884242086Sdelphij	hba->u.mvfrey.inlist[index].addr = phy_addr;
885242086Sdelphij	hba->u.mvfrey.inlist[index].intrfc_len = (reqhdr->size + 3) / 4;
886242086Sdelphij
887242086Sdelphij	BUS_SPACE_WRT4_MVFREY2(inbound_write_ptr, hba->u.mvfrey.inlist_wptr);
888242086Sdelphij	BUS_SPACE_RD4_MVFREY2(inbound_write_ptr);
889242086Sdelphij
890242086Sdelphij	for (i = 0; i < millisec; i++) {
891242086Sdelphij		hptiop_intr_mvfrey(hba);
892242086Sdelphij		if (hba->config_done)
893242086Sdelphij			return 0;
894242086Sdelphij		DELAY(1000);
895242086Sdelphij	}
896242086Sdelphij	return -1;
897242086Sdelphij}
898242086Sdelphij
899175942Sscottlstatic int hptiop_send_sync_msg(struct hpt_iop_hba *hba,
900175942Sscottl					u_int32_t msg, u_int32_t millisec)
901175942Sscottl{
902175942Sscottl	u_int32_t i;
903169412Sscottl
904175942Sscottl	hba->msg_done = 0;
905175942Sscottl	hba->ops->post_msg(hba, msg);
906175942Sscottl
907175942Sscottl	for (i=0; i<millisec; i++) {
908175942Sscottl		hba->ops->iop_intr(hba);
909175942Sscottl		if (hba->msg_done)
910169412Sscottl			break;
911169412Sscottl		DELAY(1000);
912169412Sscottl	}
913169412Sscottl
914175942Sscottl	return hba->msg_done? 0 : -1;
915169412Sscottl}
916169412Sscottl
917175942Sscottlstatic int hptiop_get_config_itl(struct hpt_iop_hba * hba,
918175942Sscottl				struct hpt_iop_request_get_config * config)
919169412Sscottl{
920175942Sscottl	u_int32_t req32;
921169412Sscottl
922175942Sscottl	config->header.size = sizeof(struct hpt_iop_request_get_config);
923175942Sscottl	config->header.type = IOP_REQUEST_TYPE_GET_CONFIG;
924175942Sscottl	config->header.flags = IOP_REQUEST_FLAG_SYNC_REQUEST;
925175942Sscottl	config->header.result = IOP_RESULT_PENDING;
926175942Sscottl	config->header.context = 0;
927175942Sscottl
928175942Sscottl	req32 = BUS_SPACE_RD4_ITL(inbound_queue);
929175942Sscottl	if (req32 == IOPMU_QUEUE_EMPTY)
930169412Sscottl		return -1;
931169412Sscottl
932175942Sscottl	bus_space_write_region_4(hba->bar0t, hba->bar0h,
933175942Sscottl			req32, (u_int32_t *)config,
934175942Sscottl			sizeof(struct hpt_iop_request_header) >> 2);
935175942Sscottl
936175942Sscottl	if (hptiop_send_sync_request_itl(hba, req32, 20000)) {
937175942Sscottl		KdPrint(("hptiop: get config send cmd failed"));
938175942Sscottl		return -1;
939175942Sscottl	}
940175942Sscottl
941175942Sscottl	bus_space_read_region_4(hba->bar0t, hba->bar0h,
942175942Sscottl			req32, (u_int32_t *)config,
943175942Sscottl			sizeof(struct hpt_iop_request_get_config) >> 2);
944175942Sscottl
945175942Sscottl	BUS_SPACE_WRT4_ITL(outbound_queue, req32);
946175942Sscottl
947175942Sscottl	return 0;
948175942Sscottl}
949175942Sscottl
950175942Sscottlstatic int hptiop_get_config_mv(struct hpt_iop_hba * hba,
951175942Sscottl				struct hpt_iop_request_get_config * config)
952175942Sscottl{
953175942Sscottl	struct hpt_iop_request_get_config *req;
954175942Sscottl
955175942Sscottl	if (!(req = hba->ctlcfg_ptr))
956175942Sscottl		return -1;
957175942Sscottl
958169412Sscottl	req->header.flags = 0;
959169412Sscottl	req->header.type = IOP_REQUEST_TYPE_GET_CONFIG;
960169412Sscottl	req->header.size = sizeof(struct hpt_iop_request_get_config);
961169412Sscottl	req->header.result = IOP_RESULT_PENDING;
962175942Sscottl	req->header.context = MVIOP_CMD_TYPE_GET_CONFIG;
963169412Sscottl
964175942Sscottl	if (hptiop_send_sync_request_mv(hba, req, 20000)) {
965175942Sscottl		KdPrint(("hptiop: get config send cmd failed"));
966169412Sscottl		return -1;
967169412Sscottl	}
968169412Sscottl
969169412Sscottl	*config = *req;
970169412Sscottl	return 0;
971169412Sscottl}
972169412Sscottl
973242086Sdelphijstatic int hptiop_get_config_mvfrey(struct hpt_iop_hba * hba,
974242086Sdelphij				struct hpt_iop_request_get_config * config)
975242086Sdelphij{
976242086Sdelphij	struct hpt_iop_request_get_config *info = hba->u.mvfrey.config;
977242086Sdelphij
978242086Sdelphij	if (info->header.size != sizeof(struct hpt_iop_request_get_config) ||
979242086Sdelphij	    info->header.type != IOP_REQUEST_TYPE_GET_CONFIG) {
980242086Sdelphij		KdPrint(("hptiop: header size %x/%x type %x/%x",
981242086Sdelphij			 info->header.size, (int)sizeof(struct hpt_iop_request_get_config),
982242086Sdelphij			 info->header.type, IOP_REQUEST_TYPE_GET_CONFIG));
983242086Sdelphij		return -1;
984242086Sdelphij	}
985242086Sdelphij
986242086Sdelphij	config->interface_version = info->interface_version;
987242086Sdelphij	config->firmware_version = info->firmware_version;
988242086Sdelphij	config->max_requests = info->max_requests;
989242086Sdelphij	config->request_size = info->request_size;
990242086Sdelphij	config->max_sg_count = info->max_sg_count;
991242086Sdelphij	config->data_transfer_length = info->data_transfer_length;
992242086Sdelphij	config->alignment_mask = info->alignment_mask;
993242086Sdelphij	config->max_devices = info->max_devices;
994242086Sdelphij	config->sdram_size = info->sdram_size;
995242086Sdelphij
996242086Sdelphij	KdPrint(("hptiop: maxreq %x reqsz %x datalen %x maxdev %x sdram %x",
997242086Sdelphij		 config->max_requests, config->request_size,
998242086Sdelphij		 config->data_transfer_length, config->max_devices,
999242086Sdelphij		 config->sdram_size));
1000242086Sdelphij
1001242086Sdelphij	return 0;
1002242086Sdelphij}
1003242086Sdelphij
1004175942Sscottlstatic int hptiop_set_config_itl(struct hpt_iop_hba *hba,
1005175942Sscottl				struct hpt_iop_request_set_config *config)
1006169412Sscottl{
1007169412Sscottl	u_int32_t req32;
1008169412Sscottl
1009175942Sscottl	req32 = BUS_SPACE_RD4_ITL(inbound_queue);
1010175942Sscottl
1011169412Sscottl	if (req32 == IOPMU_QUEUE_EMPTY)
1012169412Sscottl		return -1;
1013169412Sscottl
1014175942Sscottl	config->header.size = sizeof(struct hpt_iop_request_set_config);
1015175942Sscottl	config->header.type = IOP_REQUEST_TYPE_SET_CONFIG;
1016175942Sscottl	config->header.flags = IOP_REQUEST_FLAG_SYNC_REQUEST;
1017175942Sscottl	config->header.result = IOP_RESULT_PENDING;
1018175942Sscottl	config->header.context = 0;
1019175942Sscottl
1020175942Sscottl	bus_space_write_region_4(hba->bar0t, hba->bar0h, req32,
1021175942Sscottl		(u_int32_t *)config,
1022175942Sscottl		sizeof(struct hpt_iop_request_set_config) >> 2);
1023175942Sscottl
1024175942Sscottl	if (hptiop_send_sync_request_itl(hba, req32, 20000)) {
1025175942Sscottl		KdPrint(("hptiop: set config send cmd failed"));
1026175942Sscottl		return -1;
1027175942Sscottl	}
1028175942Sscottl
1029175942Sscottl	BUS_SPACE_WRT4_ITL(outbound_queue, req32);
1030175942Sscottl
1031175942Sscottl	return 0;
1032175942Sscottl}
1033175942Sscottl
1034175942Sscottlstatic int hptiop_set_config_mv(struct hpt_iop_hba *hba,
1035175942Sscottl				struct hpt_iop_request_set_config *config)
1036175942Sscottl{
1037175942Sscottl	struct hpt_iop_request_set_config *req;
1038175942Sscottl
1039175942Sscottl	if (!(req = hba->ctlcfg_ptr))
1040175942Sscottl		return -1;
1041175942Sscottl
1042169412Sscottl	memcpy((u_int8_t *)req + sizeof(struct hpt_iop_request_header),
1043169412Sscottl		(u_int8_t *)config + sizeof(struct hpt_iop_request_header),
1044175942Sscottl		sizeof(struct hpt_iop_request_set_config) -
1045175942Sscottl			sizeof(struct hpt_iop_request_header));
1046175942Sscottl
1047169412Sscottl	req->header.flags = 0;
1048169412Sscottl	req->header.type = IOP_REQUEST_TYPE_SET_CONFIG;
1049169412Sscottl	req->header.size = sizeof(struct hpt_iop_request_set_config);
1050169412Sscottl	req->header.result = IOP_RESULT_PENDING;
1051175942Sscottl	req->header.context = MVIOP_CMD_TYPE_SET_CONFIG;
1052169412Sscottl
1053175942Sscottl	if (hptiop_send_sync_request_mv(hba, req, 20000)) {
1054175942Sscottl		KdPrint(("hptiop: set config send cmd failed"));
1055169412Sscottl		return -1;
1056169412Sscottl	}
1057169412Sscottl
1058169412Sscottl	return 0;
1059169412Sscottl}
1060169412Sscottl
1061242086Sdelphijstatic int hptiop_set_config_mvfrey(struct hpt_iop_hba *hba,
1062242086Sdelphij				struct hpt_iop_request_set_config *config)
1063242086Sdelphij{
1064242086Sdelphij	struct hpt_iop_request_set_config *req;
1065242086Sdelphij
1066242086Sdelphij	if (!(req = hba->ctlcfg_ptr))
1067242086Sdelphij		return -1;
1068242086Sdelphij
1069242086Sdelphij	memcpy((u_int8_t *)req + sizeof(struct hpt_iop_request_header),
1070242086Sdelphij		(u_int8_t *)config + sizeof(struct hpt_iop_request_header),
1071242086Sdelphij		sizeof(struct hpt_iop_request_set_config) -
1072242086Sdelphij			sizeof(struct hpt_iop_request_header));
1073242086Sdelphij
1074242086Sdelphij	req->header.type = IOP_REQUEST_TYPE_SET_CONFIG;
1075242086Sdelphij	req->header.size = sizeof(struct hpt_iop_request_set_config);
1076242086Sdelphij	req->header.result = IOP_RESULT_PENDING;
1077242086Sdelphij
1078242086Sdelphij	if (hptiop_send_sync_request_mvfrey(hba, req, 20000)) {
1079242086Sdelphij		KdPrint(("hptiop: set config send cmd failed"));
1080242086Sdelphij		return -1;
1081242086Sdelphij	}
1082242086Sdelphij
1083242086Sdelphij	return 0;
1084242086Sdelphij}
1085242086Sdelphij
1086175942Sscottlstatic int hptiop_post_ioctl_command_itl(struct hpt_iop_hba *hba,
1087175942Sscottl				u_int32_t req32,
1088175942Sscottl				struct hpt_iop_ioctl_param *pParams)
1089169412Sscottl{
1090175942Sscottl	u_int64_t temp64;
1091175942Sscottl	struct hpt_iop_request_ioctl_command req;
1092169412Sscottl
1093175942Sscottl	if ((((pParams->nInBufferSize + 3) & ~3) + pParams->nOutBufferSize) >
1094175942Sscottl			(hba->max_request_size -
1095175942Sscottl			offsetof(struct hpt_iop_request_ioctl_command, buf))) {
1096175942Sscottl		device_printf(hba->pcidev, "request size beyond max value");
1097175942Sscottl		return -1;
1098175942Sscottl	}
1099175942Sscottl
1100175942Sscottl	req.header.size = offsetof(struct hpt_iop_request_ioctl_command, buf)
1101175942Sscottl		+ pParams->nInBufferSize;
1102175942Sscottl	req.header.type = IOP_REQUEST_TYPE_IOCTL_COMMAND;
1103175942Sscottl	req.header.flags = IOP_REQUEST_FLAG_SYNC_REQUEST;
1104175942Sscottl	req.header.result = IOP_RESULT_PENDING;
1105175942Sscottl	req.header.context = req32 + (u_int64_t)(unsigned long)hba->u.itl.mu;
1106175942Sscottl	req.ioctl_code = HPT_CTL_CODE_BSD_TO_IOP(pParams->dwIoControlCode);
1107175942Sscottl	req.inbuf_size = pParams->nInBufferSize;
1108175942Sscottl	req.outbuf_size = pParams->nOutBufferSize;
1109175942Sscottl	req.bytes_returned = 0;
1110175942Sscottl
1111175942Sscottl	bus_space_write_region_4(hba->bar0t, hba->bar0h, req32, (u_int32_t *)&req,
1112175942Sscottl		offsetof(struct hpt_iop_request_ioctl_command, buf)>>2);
1113175942Sscottl
1114175942Sscottl	hptiop_lock_adapter(hba);
1115175942Sscottl
1116175942Sscottl	BUS_SPACE_WRT4_ITL(inbound_queue, req32);
1117175942Sscottl	BUS_SPACE_RD4_ITL(outbound_intstatus);
1118175942Sscottl
1119175942Sscottl	bus_space_read_region_4(hba->bar0t, hba->bar0h, req32 +
1120175942Sscottl		offsetof(struct hpt_iop_request_ioctl_command, header.context),
1121175942Sscottl		(u_int32_t *)&temp64, 2);
1122175942Sscottl	while (temp64) {
1123175942Sscottl		if (hptiop_sleep(hba, (void *)((unsigned long)hba->u.itl.mu + req32),
1124175942Sscottl				PPAUSE, "hptctl", HPT_OSM_TIMEOUT)==0)
1125175942Sscottl			break;
1126175942Sscottl		hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_RESET, 60000);
1127175942Sscottl		bus_space_read_region_4(hba->bar0t, hba->bar0h,req32 +
1128175942Sscottl			offsetof(struct hpt_iop_request_ioctl_command,
1129175942Sscottl				header.context),
1130175942Sscottl			(u_int32_t *)&temp64, 2);
1131175942Sscottl	}
1132175942Sscottl
1133175942Sscottl	hptiop_unlock_adapter(hba);
1134175942Sscottl	return 0;
1135175942Sscottl}
1136175942Sscottl
1137242086Sdelphijstatic int hptiop_bus_space_copyin(struct hpt_iop_hba *hba, u_int32_t bus,
1138242086Sdelphij									void *user, int size)
1139175942Sscottl{
1140175942Sscottl	unsigned char byte;
1141175942Sscottl	int i;
1142175942Sscottl
1143175942Sscottl	for (i=0; i<size; i++) {
1144175942Sscottl		if (copyin((u_int8_t *)user + i, &byte, 1))
1145175942Sscottl			return -1;
1146175942Sscottl		bus_space_write_1(hba->bar0t, hba->bar0h, bus + i, byte);
1147175942Sscottl	}
1148175942Sscottl
1149175942Sscottl	return 0;
1150175942Sscottl}
1151175942Sscottl
1152242086Sdelphijstatic int hptiop_bus_space_copyout(struct hpt_iop_hba *hba, u_int32_t bus,
1153242086Sdelphij									void *user, int size)
1154175942Sscottl{
1155175942Sscottl	unsigned char byte;
1156175942Sscottl	int i;
1157175942Sscottl
1158175942Sscottl	for (i=0; i<size; i++) {
1159175942Sscottl		byte = bus_space_read_1(hba->bar0t, hba->bar0h, bus + i);
1160175942Sscottl		if (copyout(&byte, (u_int8_t *)user + i, 1))
1161175942Sscottl			return -1;
1162175942Sscottl	}
1163175942Sscottl
1164175942Sscottl	return 0;
1165175942Sscottl}
1166175942Sscottl
1167175942Sscottlstatic int hptiop_do_ioctl_itl(struct hpt_iop_hba *hba,
1168175942Sscottl				struct hpt_iop_ioctl_param * pParams)
1169175942Sscottl{
1170175942Sscottl	u_int32_t req32;
1171175942Sscottl	u_int32_t result;
1172175942Sscottl
1173169412Sscottl	if ((pParams->Magic != HPT_IOCTL_MAGIC) &&
1174169412Sscottl		(pParams->Magic != HPT_IOCTL_MAGIC32))
1175169412Sscottl		return EFAULT;
1176175942Sscottl
1177175942Sscottl	req32 = BUS_SPACE_RD4_ITL(inbound_queue);
1178175942Sscottl	if (req32 == IOPMU_QUEUE_EMPTY)
1179169412Sscottl		return EFAULT;
1180169412Sscottl
1181169412Sscottl	if (pParams->nInBufferSize)
1182175942Sscottl		if (hptiop_bus_space_copyin(hba, req32 +
1183175942Sscottl			offsetof(struct hpt_iop_request_ioctl_command, buf),
1184175942Sscottl			(void *)pParams->lpInBuffer, pParams->nInBufferSize))
1185169412Sscottl			goto invalid;
1186169412Sscottl
1187175942Sscottl	if (hptiop_post_ioctl_command_itl(hba, req32, pParams))
1188169412Sscottl		goto invalid;
1189169412Sscottl
1190175942Sscottl	result = bus_space_read_4(hba->bar0t, hba->bar0h, req32 +
1191175942Sscottl			offsetof(struct hpt_iop_request_ioctl_command,
1192175942Sscottl				header.result));
1193175942Sscottl
1194175942Sscottl	if (result == IOP_RESULT_SUCCESS) {
1195169412Sscottl		if (pParams->nOutBufferSize)
1196175942Sscottl			if (hptiop_bus_space_copyout(hba, req32 +
1197175942Sscottl				offsetof(struct hpt_iop_request_ioctl_command, buf) +
1198169412Sscottl					((pParams->nInBufferSize + 3) & ~3),
1199175942Sscottl				(void *)pParams->lpOutBuffer, pParams->nOutBufferSize))
1200169412Sscottl				goto invalid;
1201169412Sscottl
1202175942Sscottl		if (pParams->lpBytesReturned) {
1203175942Sscottl			if (hptiop_bus_space_copyout(hba, req32 +
1204175942Sscottl				offsetof(struct hpt_iop_request_ioctl_command, bytes_returned),
1205175942Sscottl				(void *)pParams->lpBytesReturned, sizeof(unsigned  long)))
1206169412Sscottl				goto invalid;
1207175942Sscottl		}
1208175942Sscottl
1209175942Sscottl		BUS_SPACE_WRT4_ITL(outbound_queue, req32);
1210175942Sscottl
1211169412Sscottl		return 0;
1212169412Sscottl	} else{
1213169412Sscottlinvalid:
1214175942Sscottl		BUS_SPACE_WRT4_ITL(outbound_queue, req32);
1215175942Sscottl
1216169412Sscottl		return EFAULT;
1217169412Sscottl	}
1218169412Sscottl}
1219169412Sscottl
1220175942Sscottlstatic int hptiop_post_ioctl_command_mv(struct hpt_iop_hba *hba,
1221175942Sscottl				struct hpt_iop_request_ioctl_command *req,
1222175942Sscottl				struct hpt_iop_ioctl_param *pParams)
1223169412Sscottl{
1224175942Sscottl	u_int64_t req_phy;
1225175942Sscottl	int size = 0;
1226175942Sscottl
1227175942Sscottl	if ((((pParams->nInBufferSize + 3) & ~3) + pParams->nOutBufferSize) >
1228175942Sscottl			(hba->max_request_size -
1229175942Sscottl			offsetof(struct hpt_iop_request_ioctl_command, buf))) {
1230175942Sscottl		device_printf(hba->pcidev, "request size beyond max value");
1231169412Sscottl		return -1;
1232169412Sscottl	}
1233169412Sscottl
1234169412Sscottl	req->ioctl_code = HPT_CTL_CODE_BSD_TO_IOP(pParams->dwIoControlCode);
1235169412Sscottl	req->inbuf_size = pParams->nInBufferSize;
1236169412Sscottl	req->outbuf_size = pParams->nOutBufferSize;
1237175942Sscottl	req->header.size = offsetof(struct hpt_iop_request_ioctl_command, buf)
1238175942Sscottl					+ pParams->nInBufferSize;
1239175942Sscottl	req->header.context = (u_int64_t)MVIOP_CMD_TYPE_IOCTL;
1240169412Sscottl	req->header.type = IOP_REQUEST_TYPE_IOCTL_COMMAND;
1241169412Sscottl	req->header.result = IOP_RESULT_PENDING;
1242175942Sscottl	req->header.flags = IOP_REQUEST_FLAG_OUTPUT_CONTEXT;
1243175942Sscottl	size = req->header.size >> 8;
1244299033Saraujo	size = imin(3, size);
1245175942Sscottl	req_phy = hba->ctlcfgcmd_phy | MVIOP_MU_QUEUE_ADDR_HOST_BIT | size;
1246175942Sscottl	hptiop_mv_inbound_write(req_phy, hba);
1247169412Sscottl
1248175942Sscottl	BUS_SPACE_RD4_MV0(outbound_intmask);
1249169412Sscottl
1250175942Sscottl	while (hba->config_done == 0) {
1251175942Sscottl		if (hptiop_sleep(hba, req, PPAUSE,
1252175942Sscottl			"hptctl", HPT_OSM_TIMEOUT)==0)
1253175942Sscottl			continue;
1254175942Sscottl		hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_RESET, 60000);
1255169412Sscottl	}
1256169412Sscottl	return 0;
1257169412Sscottl}
1258169412Sscottl
1259175942Sscottlstatic int hptiop_do_ioctl_mv(struct hpt_iop_hba *hba,
1260175942Sscottl				struct hpt_iop_ioctl_param *pParams)
1261175942Sscottl{
1262175942Sscottl	struct hpt_iop_request_ioctl_command *req;
1263175942Sscottl
1264175942Sscottl	if ((pParams->Magic != HPT_IOCTL_MAGIC) &&
1265175942Sscottl		(pParams->Magic != HPT_IOCTL_MAGIC32))
1266175942Sscottl		return EFAULT;
1267175942Sscottl
1268175942Sscottl	req = (struct hpt_iop_request_ioctl_command *)(hba->ctlcfg_ptr);
1269175942Sscottl	hba->config_done = 0;
1270175942Sscottl	hptiop_lock_adapter(hba);
1271175942Sscottl	if (pParams->nInBufferSize)
1272175942Sscottl		if (copyin((void *)pParams->lpInBuffer,
1273175942Sscottl				req->buf, pParams->nInBufferSize))
1274175942Sscottl			goto invalid;
1275175942Sscottl	if (hptiop_post_ioctl_command_mv(hba, req, pParams))
1276175942Sscottl		goto invalid;
1277175942Sscottl
1278175942Sscottl	if (hba->config_done == 1) {
1279175942Sscottl		if (pParams->nOutBufferSize)
1280175942Sscottl			if (copyout(req->buf +
1281175942Sscottl				((pParams->nInBufferSize + 3) & ~3),
1282175942Sscottl				(void *)pParams->lpOutBuffer,
1283175942Sscottl				pParams->nOutBufferSize))
1284175942Sscottl				goto invalid;
1285175942Sscottl
1286175942Sscottl		if (pParams->lpBytesReturned)
1287175942Sscottl			if (copyout(&req->bytes_returned,
1288175942Sscottl				(void*)pParams->lpBytesReturned,
1289175942Sscottl				sizeof(u_int32_t)))
1290175942Sscottl				goto invalid;
1291175942Sscottl		hptiop_unlock_adapter(hba);
1292175942Sscottl		return 0;
1293175942Sscottl	} else{
1294175942Sscottlinvalid:
1295175942Sscottl		hptiop_unlock_adapter(hba);
1296175942Sscottl		return EFAULT;
1297175942Sscottl	}
1298175942Sscottl}
1299175942Sscottl
1300242086Sdelphijstatic int hptiop_post_ioctl_command_mvfrey(struct hpt_iop_hba *hba,
1301242086Sdelphij				struct hpt_iop_request_ioctl_command *req,
1302242086Sdelphij				struct hpt_iop_ioctl_param *pParams)
1303242086Sdelphij{
1304242086Sdelphij	u_int64_t phy_addr;
1305242086Sdelphij	u_int32_t index;
1306242086Sdelphij
1307242086Sdelphij	phy_addr = hba->ctlcfgcmd_phy;
1308242086Sdelphij
1309242086Sdelphij	if ((((pParams->nInBufferSize + 3) & ~3) + pParams->nOutBufferSize) >
1310242086Sdelphij			(hba->max_request_size -
1311242086Sdelphij			offsetof(struct hpt_iop_request_ioctl_command, buf))) {
1312242086Sdelphij		device_printf(hba->pcidev, "request size beyond max value");
1313242086Sdelphij		return -1;
1314242086Sdelphij	}
1315242086Sdelphij
1316242086Sdelphij	req->ioctl_code = HPT_CTL_CODE_BSD_TO_IOP(pParams->dwIoControlCode);
1317242086Sdelphij	req->inbuf_size = pParams->nInBufferSize;
1318242086Sdelphij	req->outbuf_size = pParams->nOutBufferSize;
1319242086Sdelphij	req->header.size = offsetof(struct hpt_iop_request_ioctl_command, buf)
1320242086Sdelphij					+ pParams->nInBufferSize;
1321242086Sdelphij
1322242086Sdelphij	req->header.type = IOP_REQUEST_TYPE_IOCTL_COMMAND;
1323242086Sdelphij	req->header.result = IOP_RESULT_PENDING;
1324242086Sdelphij
1325242086Sdelphij	req->header.flags = IOP_REQUEST_FLAG_SYNC_REQUEST
1326242086Sdelphij						| IOP_REQUEST_FLAG_OUTPUT_CONTEXT
1327242086Sdelphij						| IOP_REQUEST_FLAG_ADDR_BITS
1328242086Sdelphij						| ((phy_addr >> 16) & 0xffff0000);
1329242086Sdelphij	req->header.context = ((phy_addr & 0xffffffff) << 32 )
1330242086Sdelphij						| IOPMU_QUEUE_ADDR_HOST_BIT | req->header.type;
1331242086Sdelphij
1332242086Sdelphij	hba->u.mvfrey.inlist_wptr++;
1333242086Sdelphij	index = hba->u.mvfrey.inlist_wptr & 0x3fff;
1334242086Sdelphij
1335242086Sdelphij	if (index == hba->u.mvfrey.list_count) {
1336242086Sdelphij		index = 0;
1337242086Sdelphij		hba->u.mvfrey.inlist_wptr &= ~0x3fff;
1338242086Sdelphij		hba->u.mvfrey.inlist_wptr ^= CL_POINTER_TOGGLE;
1339242086Sdelphij	}
1340242086Sdelphij
1341242086Sdelphij	hba->u.mvfrey.inlist[index].addr = phy_addr;
1342242086Sdelphij	hba->u.mvfrey.inlist[index].intrfc_len = (req->header.size + 3) / 4;
1343242086Sdelphij
1344242086Sdelphij	BUS_SPACE_WRT4_MVFREY2(inbound_write_ptr, hba->u.mvfrey.inlist_wptr);
1345242086Sdelphij	BUS_SPACE_RD4_MVFREY2(inbound_write_ptr);
1346242086Sdelphij
1347242086Sdelphij	while (hba->config_done == 0) {
1348242086Sdelphij		if (hptiop_sleep(hba, req, PPAUSE,
1349242086Sdelphij			"hptctl", HPT_OSM_TIMEOUT)==0)
1350242086Sdelphij			continue;
1351242086Sdelphij		hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_RESET, 60000);
1352242086Sdelphij	}
1353242086Sdelphij	return 0;
1354242086Sdelphij}
1355242086Sdelphij
1356242086Sdelphijstatic int hptiop_do_ioctl_mvfrey(struct hpt_iop_hba *hba,
1357242086Sdelphij				struct hpt_iop_ioctl_param *pParams)
1358242086Sdelphij{
1359242086Sdelphij	struct hpt_iop_request_ioctl_command *req;
1360242086Sdelphij
1361242086Sdelphij	if ((pParams->Magic != HPT_IOCTL_MAGIC) &&
1362242086Sdelphij		(pParams->Magic != HPT_IOCTL_MAGIC32))
1363242086Sdelphij		return EFAULT;
1364242086Sdelphij
1365242086Sdelphij	req = (struct hpt_iop_request_ioctl_command *)(hba->ctlcfg_ptr);
1366242086Sdelphij	hba->config_done = 0;
1367242086Sdelphij	hptiop_lock_adapter(hba);
1368242086Sdelphij	if (pParams->nInBufferSize)
1369242086Sdelphij		if (copyin((void *)pParams->lpInBuffer,
1370242086Sdelphij				req->buf, pParams->nInBufferSize))
1371242086Sdelphij			goto invalid;
1372242086Sdelphij	if (hptiop_post_ioctl_command_mvfrey(hba, req, pParams))
1373242086Sdelphij		goto invalid;
1374242086Sdelphij
1375242086Sdelphij	if (hba->config_done == 1) {
1376242086Sdelphij		if (pParams->nOutBufferSize)
1377242086Sdelphij			if (copyout(req->buf +
1378242086Sdelphij				((pParams->nInBufferSize + 3) & ~3),
1379242086Sdelphij				(void *)pParams->lpOutBuffer,
1380242086Sdelphij				pParams->nOutBufferSize))
1381242086Sdelphij				goto invalid;
1382242086Sdelphij
1383242086Sdelphij		if (pParams->lpBytesReturned)
1384242086Sdelphij			if (copyout(&req->bytes_returned,
1385242086Sdelphij				(void*)pParams->lpBytesReturned,
1386242086Sdelphij				sizeof(u_int32_t)))
1387242086Sdelphij				goto invalid;
1388242086Sdelphij		hptiop_unlock_adapter(hba);
1389242086Sdelphij		return 0;
1390242086Sdelphij	} else{
1391242086Sdelphijinvalid:
1392242086Sdelphij		hptiop_unlock_adapter(hba);
1393242086Sdelphij		return EFAULT;
1394242086Sdelphij	}
1395242086Sdelphij}
1396242086Sdelphij
1397169412Sscottlstatic int  hptiop_rescan_bus(struct hpt_iop_hba * hba)
1398169412Sscottl{
1399169412Sscottl	union ccb           *ccb;
1400203108Smav
1401203108Smav	if ((ccb = xpt_alloc_ccb()) == NULL)
1402203108Smav		return(ENOMEM);
1403249468Smav	if (xpt_create_path(&ccb->ccb_h.path, NULL, cam_sim_path(hba->sim),
1404203108Smav		CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
1405203108Smav		xpt_free_ccb(ccb);
1406169412Sscottl		return(EIO);
1407203108Smav	}
1408203108Smav	xpt_rescan(ccb);
1409169412Sscottl	return(0);
1410169412Sscottl}
1411169412Sscottl
1412169412Sscottlstatic  bus_dmamap_callback_t   hptiop_map_srb;
1413169412Sscottlstatic  bus_dmamap_callback_t   hptiop_post_scsi_command;
1414175942Sscottlstatic  bus_dmamap_callback_t   hptiop_mv_map_ctlcfg;
1415242086Sdelphijstatic	bus_dmamap_callback_t	hptiop_mvfrey_map_ctlcfg;
1416169412Sscottl
1417175942Sscottlstatic int hptiop_alloc_pci_res_itl(struct hpt_iop_hba *hba)
1418175942Sscottl{
1419175942Sscottl	hba->bar0_rid = 0x10;
1420175942Sscottl	hba->bar0_res = bus_alloc_resource_any(hba->pcidev,
1421175942Sscottl			SYS_RES_MEMORY, &hba->bar0_rid, RF_ACTIVE);
1422175942Sscottl
1423175942Sscottl	if (hba->bar0_res == NULL) {
1424175942Sscottl		device_printf(hba->pcidev,
1425175942Sscottl			"failed to get iop base adrress.\n");
1426175942Sscottl		return -1;
1427175942Sscottl	}
1428175942Sscottl	hba->bar0t = rman_get_bustag(hba->bar0_res);
1429175942Sscottl	hba->bar0h = rman_get_bushandle(hba->bar0_res);
1430175942Sscottl	hba->u.itl.mu = (struct hpt_iopmu_itl *)
1431175942Sscottl				rman_get_virtual(hba->bar0_res);
1432175942Sscottl
1433175942Sscottl	if (!hba->u.itl.mu) {
1434175942Sscottl		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1435175942Sscottl					hba->bar0_rid, hba->bar0_res);
1436175942Sscottl		device_printf(hba->pcidev, "alloc mem res failed\n");
1437175942Sscottl		return -1;
1438175942Sscottl	}
1439175942Sscottl
1440175942Sscottl	return 0;
1441175942Sscottl}
1442175942Sscottl
1443175942Sscottlstatic int hptiop_alloc_pci_res_mv(struct hpt_iop_hba *hba)
1444175942Sscottl{
1445175942Sscottl	hba->bar0_rid = 0x10;
1446175942Sscottl	hba->bar0_res = bus_alloc_resource_any(hba->pcidev,
1447175942Sscottl			SYS_RES_MEMORY, &hba->bar0_rid, RF_ACTIVE);
1448175942Sscottl
1449175942Sscottl	if (hba->bar0_res == NULL) {
1450175942Sscottl		device_printf(hba->pcidev, "failed to get iop bar0.\n");
1451175942Sscottl		return -1;
1452175942Sscottl	}
1453175942Sscottl	hba->bar0t = rman_get_bustag(hba->bar0_res);
1454175942Sscottl	hba->bar0h = rman_get_bushandle(hba->bar0_res);
1455175942Sscottl	hba->u.mv.regs = (struct hpt_iopmv_regs *)
1456175942Sscottl				rman_get_virtual(hba->bar0_res);
1457175942Sscottl
1458175942Sscottl	if (!hba->u.mv.regs) {
1459175942Sscottl		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1460175942Sscottl					hba->bar0_rid, hba->bar0_res);
1461175942Sscottl		device_printf(hba->pcidev, "alloc bar0 mem res failed\n");
1462175942Sscottl		return -1;
1463175942Sscottl	}
1464175942Sscottl
1465175942Sscottl	hba->bar2_rid = 0x18;
1466175942Sscottl	hba->bar2_res = bus_alloc_resource_any(hba->pcidev,
1467175942Sscottl			SYS_RES_MEMORY, &hba->bar2_rid, RF_ACTIVE);
1468175942Sscottl
1469175942Sscottl	if (hba->bar2_res == NULL) {
1470175942Sscottl		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1471175942Sscottl					hba->bar0_rid, hba->bar0_res);
1472175942Sscottl		device_printf(hba->pcidev, "failed to get iop bar2.\n");
1473175942Sscottl		return -1;
1474175942Sscottl	}
1475175942Sscottl
1476175942Sscottl	hba->bar2t = rman_get_bustag(hba->bar2_res);
1477175942Sscottl	hba->bar2h = rman_get_bushandle(hba->bar2_res);
1478175942Sscottl	hba->u.mv.mu = (struct hpt_iopmu_mv *)rman_get_virtual(hba->bar2_res);
1479175942Sscottl
1480175942Sscottl	if (!hba->u.mv.mu) {
1481175942Sscottl		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1482175942Sscottl					hba->bar0_rid, hba->bar0_res);
1483175942Sscottl		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1484175942Sscottl					hba->bar2_rid, hba->bar2_res);
1485175942Sscottl		device_printf(hba->pcidev, "alloc mem bar2 res failed\n");
1486175942Sscottl		return -1;
1487175942Sscottl	}
1488175942Sscottl
1489175942Sscottl	return 0;
1490175942Sscottl}
1491175942Sscottl
1492242086Sdelphijstatic int hptiop_alloc_pci_res_mvfrey(struct hpt_iop_hba *hba)
1493242086Sdelphij{
1494242086Sdelphij	hba->bar0_rid = 0x10;
1495242086Sdelphij	hba->bar0_res = bus_alloc_resource_any(hba->pcidev,
1496242086Sdelphij			SYS_RES_MEMORY, &hba->bar0_rid, RF_ACTIVE);
1497242086Sdelphij
1498242086Sdelphij	if (hba->bar0_res == NULL) {
1499242086Sdelphij		device_printf(hba->pcidev, "failed to get iop bar0.\n");
1500242086Sdelphij		return -1;
1501242086Sdelphij	}
1502242086Sdelphij	hba->bar0t = rman_get_bustag(hba->bar0_res);
1503242086Sdelphij	hba->bar0h = rman_get_bushandle(hba->bar0_res);
1504242086Sdelphij	hba->u.mvfrey.config = (struct hpt_iop_request_get_config *)
1505242086Sdelphij				rman_get_virtual(hba->bar0_res);
1506242086Sdelphij
1507242086Sdelphij	if (!hba->u.mvfrey.config) {
1508242086Sdelphij		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1509242086Sdelphij					hba->bar0_rid, hba->bar0_res);
1510242086Sdelphij		device_printf(hba->pcidev, "alloc bar0 mem res failed\n");
1511242086Sdelphij		return -1;
1512242086Sdelphij	}
1513242086Sdelphij
1514242086Sdelphij	hba->bar2_rid = 0x18;
1515242086Sdelphij	hba->bar2_res = bus_alloc_resource_any(hba->pcidev,
1516242086Sdelphij			SYS_RES_MEMORY, &hba->bar2_rid, RF_ACTIVE);
1517242086Sdelphij
1518242086Sdelphij	if (hba->bar2_res == NULL) {
1519242086Sdelphij		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1520242086Sdelphij					hba->bar0_rid, hba->bar0_res);
1521242086Sdelphij		device_printf(hba->pcidev, "failed to get iop bar2.\n");
1522242086Sdelphij		return -1;
1523242086Sdelphij	}
1524242086Sdelphij
1525242086Sdelphij	hba->bar2t = rman_get_bustag(hba->bar2_res);
1526242086Sdelphij	hba->bar2h = rman_get_bushandle(hba->bar2_res);
1527242086Sdelphij	hba->u.mvfrey.mu =
1528242086Sdelphij					(struct hpt_iopmu_mvfrey *)rman_get_virtual(hba->bar2_res);
1529242086Sdelphij
1530242086Sdelphij	if (!hba->u.mvfrey.mu) {
1531242086Sdelphij		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1532242086Sdelphij					hba->bar0_rid, hba->bar0_res);
1533242086Sdelphij		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1534242086Sdelphij					hba->bar2_rid, hba->bar2_res);
1535242086Sdelphij		device_printf(hba->pcidev, "alloc mem bar2 res failed\n");
1536242086Sdelphij		return -1;
1537242086Sdelphij	}
1538242086Sdelphij
1539242086Sdelphij	return 0;
1540242086Sdelphij}
1541242086Sdelphij
1542175942Sscottlstatic void hptiop_release_pci_res_itl(struct hpt_iop_hba *hba)
1543175942Sscottl{
1544175942Sscottl	if (hba->bar0_res)
1545175942Sscottl		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1546175942Sscottl			hba->bar0_rid, hba->bar0_res);
1547175942Sscottl}
1548175942Sscottl
1549175942Sscottlstatic void hptiop_release_pci_res_mv(struct hpt_iop_hba *hba)
1550175942Sscottl{
1551175942Sscottl	if (hba->bar0_res)
1552175942Sscottl		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1553175942Sscottl			hba->bar0_rid, hba->bar0_res);
1554175942Sscottl	if (hba->bar2_res)
1555175942Sscottl		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1556175942Sscottl			hba->bar2_rid, hba->bar2_res);
1557175942Sscottl}
1558175942Sscottl
1559242086Sdelphijstatic void hptiop_release_pci_res_mvfrey(struct hpt_iop_hba *hba)
1560242086Sdelphij{
1561242086Sdelphij	if (hba->bar0_res)
1562242086Sdelphij		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1563242086Sdelphij			hba->bar0_rid, hba->bar0_res);
1564242086Sdelphij	if (hba->bar2_res)
1565242086Sdelphij		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1566242086Sdelphij			hba->bar2_rid, hba->bar2_res);
1567242086Sdelphij}
1568242086Sdelphij
1569175942Sscottlstatic int hptiop_internal_memalloc_mv(struct hpt_iop_hba *hba)
1570175942Sscottl{
1571175942Sscottl	if (bus_dma_tag_create(hba->parent_dmat,
1572175942Sscottl				1,
1573175942Sscottl				0,
1574175942Sscottl				BUS_SPACE_MAXADDR_32BIT,
1575175942Sscottl				BUS_SPACE_MAXADDR,
1576175942Sscottl				NULL, NULL,
1577175942Sscottl				0x800 - 0x8,
1578175942Sscottl				1,
1579175942Sscottl				BUS_SPACE_MAXSIZE_32BIT,
1580175942Sscottl				BUS_DMA_ALLOCNOW,
1581175942Sscottl				NULL,
1582175942Sscottl				NULL,
1583242086Sdelphij				&hba->ctlcfg_dmat)) {
1584175942Sscottl		device_printf(hba->pcidev, "alloc ctlcfg_dmat failed\n");
1585175942Sscottl		return -1;
1586175942Sscottl	}
1587175942Sscottl
1588175942Sscottl	if (bus_dmamem_alloc(hba->ctlcfg_dmat, (void **)&hba->ctlcfg_ptr,
1589175942Sscottl		BUS_DMA_WAITOK | BUS_DMA_COHERENT,
1590175942Sscottl		&hba->ctlcfg_dmamap) != 0) {
1591175942Sscottl			device_printf(hba->pcidev,
1592175942Sscottl					"bus_dmamem_alloc failed!\n");
1593175942Sscottl			bus_dma_tag_destroy(hba->ctlcfg_dmat);
1594175942Sscottl			return -1;
1595175942Sscottl	}
1596175942Sscottl
1597175942Sscottl	if (bus_dmamap_load(hba->ctlcfg_dmat,
1598175942Sscottl			hba->ctlcfg_dmamap, hba->ctlcfg_ptr,
1599175942Sscottl			MVIOP_IOCTLCFG_SIZE,
1600175942Sscottl			hptiop_mv_map_ctlcfg, hba, 0)) {
1601175942Sscottl		device_printf(hba->pcidev, "bus_dmamap_load failed!\n");
1602250123Seadler		if (hba->ctlcfg_dmat) {
1603175942Sscottl			bus_dmamem_free(hba->ctlcfg_dmat,
1604175942Sscottl				hba->ctlcfg_ptr, hba->ctlcfg_dmamap);
1605175942Sscottl			bus_dma_tag_destroy(hba->ctlcfg_dmat);
1606250123Seadler		}
1607175942Sscottl		return -1;
1608175942Sscottl	}
1609175942Sscottl
1610175942Sscottl	return 0;
1611175942Sscottl}
1612175942Sscottl
1613242086Sdelphijstatic int hptiop_internal_memalloc_mvfrey(struct hpt_iop_hba *hba)
1614242086Sdelphij{
1615242086Sdelphij	u_int32_t list_count = BUS_SPACE_RD4_MVFREY2(inbound_conf_ctl);
1616242086Sdelphij
1617242086Sdelphij	list_count >>= 16;
1618242086Sdelphij
1619242086Sdelphij	if (list_count == 0) {
1620242086Sdelphij		return -1;
1621242086Sdelphij	}
1622242086Sdelphij
1623242086Sdelphij	hba->u.mvfrey.list_count = list_count;
1624242086Sdelphij	hba->u.mvfrey.internal_mem_size = 0x800
1625242086Sdelphij							+ list_count * sizeof(struct mvfrey_inlist_entry)
1626242086Sdelphij							+ list_count * sizeof(struct mvfrey_outlist_entry)
1627242086Sdelphij							+ sizeof(int);
1628242086Sdelphij	if (bus_dma_tag_create(hba->parent_dmat,
1629242086Sdelphij				1,
1630242086Sdelphij				0,
1631242086Sdelphij				BUS_SPACE_MAXADDR_32BIT,
1632242086Sdelphij				BUS_SPACE_MAXADDR,
1633242086Sdelphij				NULL, NULL,
1634242086Sdelphij				hba->u.mvfrey.internal_mem_size,
1635242086Sdelphij				1,
1636242086Sdelphij				BUS_SPACE_MAXSIZE_32BIT,
1637242086Sdelphij				BUS_DMA_ALLOCNOW,
1638242086Sdelphij				NULL,
1639242086Sdelphij				NULL,
1640242086Sdelphij				&hba->ctlcfg_dmat)) {
1641242086Sdelphij		device_printf(hba->pcidev, "alloc ctlcfg_dmat failed\n");
1642242086Sdelphij		return -1;
1643242086Sdelphij	}
1644242086Sdelphij
1645242086Sdelphij	if (bus_dmamem_alloc(hba->ctlcfg_dmat, (void **)&hba->ctlcfg_ptr,
1646242086Sdelphij		BUS_DMA_WAITOK | BUS_DMA_COHERENT,
1647242086Sdelphij		&hba->ctlcfg_dmamap) != 0) {
1648242086Sdelphij			device_printf(hba->pcidev,
1649242086Sdelphij					"bus_dmamem_alloc failed!\n");
1650242086Sdelphij			bus_dma_tag_destroy(hba->ctlcfg_dmat);
1651242086Sdelphij			return -1;
1652242086Sdelphij	}
1653242086Sdelphij
1654242086Sdelphij	if (bus_dmamap_load(hba->ctlcfg_dmat,
1655242086Sdelphij			hba->ctlcfg_dmamap, hba->ctlcfg_ptr,
1656242086Sdelphij			hba->u.mvfrey.internal_mem_size,
1657242086Sdelphij			hptiop_mvfrey_map_ctlcfg, hba, 0)) {
1658242086Sdelphij		device_printf(hba->pcidev, "bus_dmamap_load failed!\n");
1659250050Sdelphij		if (hba->ctlcfg_dmat) {
1660242086Sdelphij			bus_dmamem_free(hba->ctlcfg_dmat,
1661242086Sdelphij				hba->ctlcfg_ptr, hba->ctlcfg_dmamap);
1662242086Sdelphij			bus_dma_tag_destroy(hba->ctlcfg_dmat);
1663250050Sdelphij		}
1664242086Sdelphij		return -1;
1665242086Sdelphij	}
1666242086Sdelphij
1667242086Sdelphij	return 0;
1668242086Sdelphij}
1669242086Sdelphij
1670242086Sdelphijstatic int hptiop_internal_memfree_itl(struct hpt_iop_hba *hba) {
1671242086Sdelphij	return 0;
1672242086Sdelphij}
1673242086Sdelphij
1674175942Sscottlstatic int hptiop_internal_memfree_mv(struct hpt_iop_hba *hba)
1675175942Sscottl{
1676175942Sscottl	if (hba->ctlcfg_dmat) {
1677175942Sscottl		bus_dmamap_unload(hba->ctlcfg_dmat, hba->ctlcfg_dmamap);
1678175942Sscottl		bus_dmamem_free(hba->ctlcfg_dmat,
1679175942Sscottl					hba->ctlcfg_ptr, hba->ctlcfg_dmamap);
1680175942Sscottl		bus_dma_tag_destroy(hba->ctlcfg_dmat);
1681175942Sscottl	}
1682175942Sscottl
1683175942Sscottl	return 0;
1684175942Sscottl}
1685175942Sscottl
1686242086Sdelphijstatic int hptiop_internal_memfree_mvfrey(struct hpt_iop_hba *hba)
1687242086Sdelphij{
1688242086Sdelphij	if (hba->ctlcfg_dmat) {
1689242086Sdelphij		bus_dmamap_unload(hba->ctlcfg_dmat, hba->ctlcfg_dmamap);
1690242086Sdelphij		bus_dmamem_free(hba->ctlcfg_dmat,
1691242086Sdelphij					hba->ctlcfg_ptr, hba->ctlcfg_dmamap);
1692242086Sdelphij		bus_dma_tag_destroy(hba->ctlcfg_dmat);
1693242086Sdelphij	}
1694242086Sdelphij
1695242086Sdelphij	return 0;
1696242086Sdelphij}
1697242086Sdelphij
1698242086Sdelphijstatic int hptiop_reset_comm_mvfrey(struct hpt_iop_hba *hba)
1699242086Sdelphij{
1700242086Sdelphij	u_int32_t i = 100;
1701242086Sdelphij
1702242086Sdelphij	if (hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_RESET_COMM, 3000))
1703242086Sdelphij		return -1;
1704242086Sdelphij
1705242086Sdelphij	/* wait 100ms for MCU ready */
1706242086Sdelphij	while(i--) {
1707242086Sdelphij		DELAY(1000);
1708242086Sdelphij	}
1709242086Sdelphij
1710242086Sdelphij	BUS_SPACE_WRT4_MVFREY2(inbound_base,
1711242086Sdelphij							hba->u.mvfrey.inlist_phy & 0xffffffff);
1712242086Sdelphij	BUS_SPACE_WRT4_MVFREY2(inbound_base_high,
1713242086Sdelphij							(hba->u.mvfrey.inlist_phy >> 16) >> 16);
1714242086Sdelphij
1715242086Sdelphij	BUS_SPACE_WRT4_MVFREY2(outbound_base,
1716242086Sdelphij							hba->u.mvfrey.outlist_phy & 0xffffffff);
1717242086Sdelphij	BUS_SPACE_WRT4_MVFREY2(outbound_base_high,
1718242086Sdelphij							(hba->u.mvfrey.outlist_phy >> 16) >> 16);
1719242086Sdelphij
1720242086Sdelphij	BUS_SPACE_WRT4_MVFREY2(outbound_shadow_base,
1721242086Sdelphij							hba->u.mvfrey.outlist_cptr_phy & 0xffffffff);
1722242086Sdelphij	BUS_SPACE_WRT4_MVFREY2(outbound_shadow_base_high,
1723242086Sdelphij							(hba->u.mvfrey.outlist_cptr_phy >> 16) >> 16);
1724242086Sdelphij
1725242086Sdelphij	hba->u.mvfrey.inlist_wptr = (hba->u.mvfrey.list_count - 1)
1726242086Sdelphij								| CL_POINTER_TOGGLE;
1727242086Sdelphij	*hba->u.mvfrey.outlist_cptr = (hba->u.mvfrey.list_count - 1)
1728242086Sdelphij								| CL_POINTER_TOGGLE;
1729242086Sdelphij	hba->u.mvfrey.outlist_rptr = hba->u.mvfrey.list_count - 1;
1730242086Sdelphij
1731242086Sdelphij	return 0;
1732242086Sdelphij}
1733242086Sdelphij
1734169412Sscottl/*
1735169412Sscottl * CAM driver interface
1736169412Sscottl */
1737169412Sscottlstatic device_method_t driver_methods[] = {
1738169412Sscottl	/* Device interface */
1739169412Sscottl	DEVMETHOD(device_probe,     hptiop_probe),
1740169412Sscottl	DEVMETHOD(device_attach,    hptiop_attach),
1741169412Sscottl	DEVMETHOD(device_detach,    hptiop_detach),
1742169412Sscottl	DEVMETHOD(device_shutdown,  hptiop_shutdown),
1743169412Sscottl	{ 0, 0 }
1744169412Sscottl};
1745169412Sscottl
1746175942Sscottlstatic struct hptiop_adapter_ops hptiop_itl_ops = {
1747242086Sdelphij	.family	           = INTEL_BASED_IOP,
1748175942Sscottl	.iop_wait_ready    = hptiop_wait_ready_itl,
1749175942Sscottl	.internal_memalloc = 0,
1750242086Sdelphij	.internal_memfree  = hptiop_internal_memfree_itl,
1751175942Sscottl	.alloc_pci_res     = hptiop_alloc_pci_res_itl,
1752175942Sscottl	.release_pci_res   = hptiop_release_pci_res_itl,
1753175942Sscottl	.enable_intr       = hptiop_enable_intr_itl,
1754175942Sscottl	.disable_intr      = hptiop_disable_intr_itl,
1755175942Sscottl	.get_config        = hptiop_get_config_itl,
1756175942Sscottl	.set_config        = hptiop_set_config_itl,
1757175942Sscottl	.iop_intr          = hptiop_intr_itl,
1758175942Sscottl	.post_msg          = hptiop_post_msg_itl,
1759175942Sscottl	.post_req          = hptiop_post_req_itl,
1760175942Sscottl	.do_ioctl          = hptiop_do_ioctl_itl,
1761242086Sdelphij	.reset_comm        = 0,
1762175942Sscottl};
1763175942Sscottl
1764175942Sscottlstatic struct hptiop_adapter_ops hptiop_mv_ops = {
1765242086Sdelphij	.family	           = MV_BASED_IOP,
1766175942Sscottl	.iop_wait_ready    = hptiop_wait_ready_mv,
1767175942Sscottl	.internal_memalloc = hptiop_internal_memalloc_mv,
1768175942Sscottl	.internal_memfree  = hptiop_internal_memfree_mv,
1769175942Sscottl	.alloc_pci_res     = hptiop_alloc_pci_res_mv,
1770175942Sscottl	.release_pci_res   = hptiop_release_pci_res_mv,
1771175942Sscottl	.enable_intr       = hptiop_enable_intr_mv,
1772175942Sscottl	.disable_intr      = hptiop_disable_intr_mv,
1773175942Sscottl	.get_config        = hptiop_get_config_mv,
1774175942Sscottl	.set_config        = hptiop_set_config_mv,
1775175942Sscottl	.iop_intr          = hptiop_intr_mv,
1776175942Sscottl	.post_msg          = hptiop_post_msg_mv,
1777175942Sscottl	.post_req          = hptiop_post_req_mv,
1778175942Sscottl	.do_ioctl          = hptiop_do_ioctl_mv,
1779242086Sdelphij	.reset_comm        = 0,
1780175942Sscottl};
1781175942Sscottl
1782242086Sdelphijstatic struct hptiop_adapter_ops hptiop_mvfrey_ops = {
1783242086Sdelphij	.family	           = MVFREY_BASED_IOP,
1784242086Sdelphij	.iop_wait_ready    = hptiop_wait_ready_mvfrey,
1785242086Sdelphij	.internal_memalloc = hptiop_internal_memalloc_mvfrey,
1786242086Sdelphij	.internal_memfree  = hptiop_internal_memfree_mvfrey,
1787242086Sdelphij	.alloc_pci_res     = hptiop_alloc_pci_res_mvfrey,
1788242086Sdelphij	.release_pci_res   = hptiop_release_pci_res_mvfrey,
1789242086Sdelphij	.enable_intr       = hptiop_enable_intr_mvfrey,
1790242086Sdelphij	.disable_intr      = hptiop_disable_intr_mvfrey,
1791242086Sdelphij	.get_config        = hptiop_get_config_mvfrey,
1792242086Sdelphij	.set_config        = hptiop_set_config_mvfrey,
1793242086Sdelphij	.iop_intr          = hptiop_intr_mvfrey,
1794242086Sdelphij	.post_msg          = hptiop_post_msg_mvfrey,
1795242086Sdelphij	.post_req          = hptiop_post_req_mvfrey,
1796242086Sdelphij	.do_ioctl          = hptiop_do_ioctl_mvfrey,
1797242086Sdelphij	.reset_comm        = hptiop_reset_comm_mvfrey,
1798242086Sdelphij};
1799242086Sdelphij
1800169412Sscottlstatic driver_t hptiop_pci_driver = {
1801169412Sscottl	driver_name,
1802169412Sscottl	driver_methods,
1803169412Sscottl	sizeof(struct hpt_iop_hba)
1804169412Sscottl};
1805169412Sscottl
1806169412SscottlDRIVER_MODULE(hptiop, pci, hptiop_pci_driver, hptiop_devclass, 0, 0);
1807236379SeadlerMODULE_DEPEND(hptiop, cam, 1, 1, 1);
1808169412Sscottl
1809169412Sscottlstatic int hptiop_probe(device_t dev)
1810169412Sscottl{
1811169412Sscottl	struct hpt_iop_hba *hba;
1812175942Sscottl	u_int32_t id;
1813175942Sscottl	static char buf[256];
1814175942Sscottl	int sas = 0;
1815175942Sscottl	struct hptiop_adapter_ops *ops;
1816169412Sscottl
1817175942Sscottl	if (pci_get_vendor(dev) != 0x1103)
1818175942Sscottl		return (ENXIO);
1819175942Sscottl
1820175942Sscottl	id = pci_get_device(dev);
1821175942Sscottl
1822175942Sscottl	switch (id) {
1823242086Sdelphij		case 0x4520:
1824252851Sdelphij		case 0x4521:
1825242086Sdelphij		case 0x4522:
1826242086Sdelphij			sas = 1;
1827252851Sdelphij		case 0x3620:
1828252851Sdelphij		case 0x3622:
1829252851Sdelphij		case 0x3640:
1830242086Sdelphij			ops = &hptiop_mvfrey_ops;
1831242086Sdelphij			break;
1832239084Sdelphij		case 0x4210:
1833239084Sdelphij		case 0x4211:
1834239084Sdelphij		case 0x4310:
1835239084Sdelphij		case 0x4311:
1836239084Sdelphij		case 0x4320:
1837224583Sdelphij		case 0x4321:
1838239084Sdelphij 		case 0x4322:
1839175942Sscottl			sas = 1;
1840175942Sscottl		case 0x3220:
1841175942Sscottl		case 0x3320:
1842175942Sscottl		case 0x3410:
1843175942Sscottl		case 0x3520:
1844175942Sscottl		case 0x3510:
1845175942Sscottl		case 0x3511:
1846175942Sscottl		case 0x3521:
1847175942Sscottl		case 0x3522:
1848239084Sdelphij		case 0x3530:
1849175942Sscottl		case 0x3540:
1850239084Sdelphij		case 0x3560:
1851175942Sscottl			ops = &hptiop_itl_ops;
1852175942Sscottl			break;
1853239084Sdelphij		case 0x3020:
1854175942Sscottl		case 0x3120:
1855175942Sscottl		case 0x3122:
1856175942Sscottl			ops = &hptiop_mv_ops;
1857175942Sscottl			break;
1858175942Sscottl		default:
1859175942Sscottl			return (ENXIO);
1860169412Sscottl	}
1861175942Sscottl
1862175942Sscottl	device_printf(dev, "adapter at PCI %d:%d:%d, IRQ %d\n",
1863175942Sscottl		pci_get_bus(dev), pci_get_slot(dev),
1864175942Sscottl		pci_get_function(dev), pci_get_irq(dev));
1865175942Sscottl
1866175942Sscottl	sprintf(buf, "RocketRAID %x %s Controller\n",
1867175942Sscottl				id, sas ? "SAS" : "SATA");
1868175942Sscottl	device_set_desc_copy(dev, buf);
1869175942Sscottl
1870175942Sscottl	hba = (struct hpt_iop_hba *)device_get_softc(dev);
1871175942Sscottl	bzero(hba, sizeof(struct hpt_iop_hba));
1872175942Sscottl	hba->ops = ops;
1873175942Sscottl
1874175942Sscottl	KdPrint(("hba->ops=%p\n", hba->ops));
1875175942Sscottl	return 0;
1876169412Sscottl}
1877169412Sscottl
1878169412Sscottlstatic int hptiop_attach(device_t dev)
1879169412Sscottl{
1880175942Sscottl	struct hpt_iop_hba *hba = (struct hpt_iop_hba *)device_get_softc(dev);
1881169412Sscottl	struct hpt_iop_request_get_config  iop_config;
1882169412Sscottl	struct hpt_iop_request_set_config  set_config;
1883169412Sscottl	int rid = 0;
1884169412Sscottl	struct cam_devq *devq;
1885169412Sscottl	struct ccb_setasync ccb;
1886169412Sscottl	u_int32_t unit = device_get_unit(dev);
1887169412Sscottl
1888175942Sscottl	device_printf(dev, "%d RocketRAID 3xxx/4xxx controller driver %s\n",
1889175942Sscottl			unit, driver_version);
1890169412Sscottl
1891175942Sscottl	KdPrint(("hptiop: attach(%d, %d/%d/%d) ops=%p\n", unit,
1892175942Sscottl		pci_get_bus(dev), pci_get_slot(dev),
1893175942Sscottl		pci_get_function(dev), hba->ops));
1894175942Sscottl
1895169412Sscottl	pci_enable_busmaster(dev);
1896169412Sscottl	hba->pcidev = dev;
1897169412Sscottl	hba->pciunit = unit;
1898169412Sscottl
1899175942Sscottl	if (hba->ops->alloc_pci_res(hba))
1900169412Sscottl		return ENXIO;
1901169412Sscottl
1902175942Sscottl	if (hba->ops->iop_wait_ready(hba, 2000)) {
1903175942Sscottl		device_printf(dev, "adapter is not ready\n");
1904175942Sscottl		goto release_pci_res;
1905169412Sscottl	}
1906169412Sscottl
1907169412Sscottl	mtx_init(&hba->lock, "hptioplock", NULL, MTX_DEF);
1908169412Sscottl
1909232854Sscottl	if (bus_dma_tag_create(bus_get_dma_tag(dev),/* PCI parent */
1910169412Sscottl			1,  /* alignment */
1911169412Sscottl			0, /* boundary */
1912169412Sscottl			BUS_SPACE_MAXADDR,  /* lowaddr */
1913169412Sscottl			BUS_SPACE_MAXADDR,  /* highaddr */
1914169412Sscottl			NULL, NULL,         /* filter, filterarg */
1915169412Sscottl			BUS_SPACE_MAXSIZE_32BIT,    /* maxsize */
1916169412Sscottl			BUS_SPACE_UNRESTRICTED, /* nsegments */
1917169412Sscottl			BUS_SPACE_MAXSIZE_32BIT,    /* maxsegsize */
1918169412Sscottl			0,      /* flags */
1919169412Sscottl			NULL,   /* lockfunc */
1920169412Sscottl			NULL,       /* lockfuncarg */
1921169412Sscottl			&hba->parent_dmat   /* tag */))
1922169412Sscottl	{
1923175942Sscottl		device_printf(dev, "alloc parent_dmat failed\n");
1924175942Sscottl		goto release_pci_res;
1925169412Sscottl	}
1926169412Sscottl
1927242086Sdelphij	if (hba->ops->family == MV_BASED_IOP) {
1928175942Sscottl		if (hba->ops->internal_memalloc(hba)) {
1929175942Sscottl			device_printf(dev, "alloc srb_dmat failed\n");
1930175942Sscottl			goto destroy_parent_tag;
1931175942Sscottl		}
1932175942Sscottl	}
1933175942Sscottl
1934175942Sscottl	if (hba->ops->get_config(hba, &iop_config)) {
1935175942Sscottl		device_printf(dev, "get iop config failed.\n");
1936175942Sscottl		goto get_config_failed;
1937175942Sscottl	}
1938175942Sscottl
1939175942Sscottl	hba->firmware_version = iop_config.firmware_version;
1940175942Sscottl	hba->interface_version = iop_config.interface_version;
1941175942Sscottl	hba->max_requests = iop_config.max_requests;
1942175942Sscottl	hba->max_devices = iop_config.max_devices;
1943175942Sscottl	hba->max_request_size = iop_config.request_size;
1944175942Sscottl	hba->max_sg_count = iop_config.max_sg_count;
1945175942Sscottl
1946242086Sdelphij	if (hba->ops->family == MVFREY_BASED_IOP) {
1947242086Sdelphij		if (hba->ops->internal_memalloc(hba)) {
1948242086Sdelphij			device_printf(dev, "alloc srb_dmat failed\n");
1949242086Sdelphij			goto destroy_parent_tag;
1950242086Sdelphij		}
1951242086Sdelphij		if (hba->ops->reset_comm(hba)) {
1952242086Sdelphij			device_printf(dev, "reset comm failed\n");
1953242086Sdelphij			goto get_config_failed;
1954242086Sdelphij		}
1955242086Sdelphij	}
1956242086Sdelphij
1957169412Sscottl	if (bus_dma_tag_create(hba->parent_dmat,/* parent */
1958169412Sscottl			4,  /* alignment */
1959169412Sscottl			BUS_SPACE_MAXADDR_32BIT+1, /* boundary */
1960169412Sscottl			BUS_SPACE_MAXADDR,  /* lowaddr */
1961169412Sscottl			BUS_SPACE_MAXADDR,  /* highaddr */
1962169412Sscottl			NULL, NULL,         /* filter, filterarg */
1963169412Sscottl			PAGE_SIZE * (hba->max_sg_count-1),  /* maxsize */
1964169412Sscottl			hba->max_sg_count,  /* nsegments */
1965169412Sscottl			0x20000,    /* maxsegsize */
1966169412Sscottl			BUS_DMA_ALLOCNOW,       /* flags */
1967169412Sscottl			busdma_lock_mutex,  /* lockfunc */
1968169412Sscottl			&hba->lock,     /* lockfuncarg */
1969169412Sscottl			&hba->io_dmat   /* tag */))
1970169412Sscottl	{
1971175942Sscottl		device_printf(dev, "alloc io_dmat failed\n");
1972175942Sscottl		goto get_config_failed;
1973169412Sscottl	}
1974169412Sscottl
1975169412Sscottl	if (bus_dma_tag_create(hba->parent_dmat,/* parent */
1976169412Sscottl			1,  /* alignment */
1977169412Sscottl			0, /* boundary */
1978169412Sscottl			BUS_SPACE_MAXADDR_32BIT,    /* lowaddr */
1979169412Sscottl			BUS_SPACE_MAXADDR,  /* highaddr */
1980169412Sscottl			NULL, NULL,         /* filter, filterarg */
1981169412Sscottl			HPT_SRB_MAX_SIZE * HPT_SRB_MAX_QUEUE_SIZE + 0x20,
1982169412Sscottl			1,  /* nsegments */
1983169412Sscottl			BUS_SPACE_MAXSIZE_32BIT,    /* maxsegsize */
1984169412Sscottl			0,      /* flags */
1985169412Sscottl			NULL,   /* lockfunc */
1986169412Sscottl			NULL,       /* lockfuncarg */
1987169412Sscottl			&hba->srb_dmat  /* tag */))
1988169412Sscottl	{
1989175942Sscottl		device_printf(dev, "alloc srb_dmat failed\n");
1990175942Sscottl		goto destroy_io_dmat;
1991169412Sscottl	}
1992169412Sscottl
1993169412Sscottl	if (bus_dmamem_alloc(hba->srb_dmat, (void **)&hba->uncached_ptr,
1994175942Sscottl			BUS_DMA_WAITOK | BUS_DMA_COHERENT,
1995175942Sscottl			&hba->srb_dmamap) != 0)
1996169412Sscottl	{
1997175942Sscottl		device_printf(dev, "srb bus_dmamem_alloc failed!\n");
1998175942Sscottl		goto destroy_srb_dmat;
1999169412Sscottl	}
2000169412Sscottl
2001169412Sscottl	if (bus_dmamap_load(hba->srb_dmat,
2002169412Sscottl			hba->srb_dmamap, hba->uncached_ptr,
2003169412Sscottl			(HPT_SRB_MAX_SIZE * HPT_SRB_MAX_QUEUE_SIZE) + 0x20,
2004169412Sscottl			hptiop_map_srb, hba, 0))
2005169412Sscottl	{
2006175942Sscottl		device_printf(dev, "bus_dmamap_load failed!\n");
2007175942Sscottl		goto srb_dmamem_free;
2008169412Sscottl	}
2009169412Sscottl
2010169412Sscottl	if ((devq = cam_simq_alloc(hba->max_requests - 1 )) == NULL) {
2011175942Sscottl		device_printf(dev, "cam_simq_alloc failed\n");
2012175942Sscottl		goto srb_dmamap_unload;
2013169412Sscottl	}
2014175942Sscottl
2015169412Sscottl	hba->sim = cam_sim_alloc(hptiop_action, hptiop_poll, driver_name,
2016269612Sjhb			hba, unit, &hba->lock, hba->max_requests - 1, 1, devq);
2017169412Sscottl	if (!hba->sim) {
2018175942Sscottl		device_printf(dev, "cam_sim_alloc failed\n");
2019169412Sscottl		cam_simq_free(devq);
2020175942Sscottl		goto srb_dmamap_unload;
2021169412Sscottl	}
2022269612Sjhb	hptiop_lock_adapter(hba);
2023175942Sscottl	if (xpt_bus_register(hba->sim, dev, 0) != CAM_SUCCESS)
2024175942Sscottl	{
2025175942Sscottl		device_printf(dev, "xpt_bus_register failed\n");
2026175942Sscottl		goto free_cam_sim;
2027169412Sscottl	}
2028169412Sscottl
2029169412Sscottl	if (xpt_create_path(&hba->path, /*periph */ NULL,
2030169412Sscottl			cam_sim_path(hba->sim), CAM_TARGET_WILDCARD,
2031175942Sscottl			CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
2032175942Sscottl		device_printf(dev, "xpt_create_path failed\n");
2033175942Sscottl		goto deregister_xpt_bus;
2034169412Sscottl	}
2035269612Sjhb	hptiop_unlock_adapter(hba);
2036169412Sscottl
2037169412Sscottl	bzero(&set_config, sizeof(set_config));
2038175942Sscottl	set_config.iop_id = unit;
2039169412Sscottl	set_config.vbus_id = cam_sim_path(hba->sim);
2040169412Sscottl	set_config.max_host_request_size = HPT_SRB_MAX_REQ_SIZE;
2041169412Sscottl
2042175942Sscottl	if (hba->ops->set_config(hba, &set_config)) {
2043175942Sscottl		device_printf(dev, "set iop config failed.\n");
2044175942Sscottl		goto free_hba_path;
2045169412Sscottl	}
2046169412Sscottl
2047169412Sscottl	xpt_setup_ccb(&ccb.ccb_h, hba->path, /*priority*/5);
2048169412Sscottl	ccb.ccb_h.func_code = XPT_SASYNC_CB;
2049169412Sscottl	ccb.event_enable = (AC_FOUND_DEVICE | AC_LOST_DEVICE);
2050169412Sscottl	ccb.callback = hptiop_async;
2051169412Sscottl	ccb.callback_arg = hba->sim;
2052169412Sscottl	xpt_action((union ccb *)&ccb);
2053169412Sscottl
2054169412Sscottl	rid = 0;
2055295790Sjhibbits	if ((hba->irq_res = bus_alloc_resource_any(hba->pcidev, SYS_RES_IRQ,
2056295790Sjhibbits			&rid, RF_SHAREABLE | RF_ACTIVE)) == NULL) {
2057175942Sscottl		device_printf(dev, "allocate irq failed!\n");
2058175942Sscottl		goto free_hba_path;
2059169412Sscottl	}
2060169412Sscottl
2061269612Sjhb	if (bus_setup_intr(hba->pcidev, hba->irq_res, INTR_TYPE_CAM | INTR_MPSAFE,
2062175942Sscottl				NULL, hptiop_pci_intr, hba, &hba->irq_handle))
2063175942Sscottl	{
2064175942Sscottl		device_printf(dev, "allocate intr function failed!\n");
2065175942Sscottl		goto free_irq_resource;
2066169412Sscottl	}
2067169412Sscottl
2068175942Sscottl	if (hptiop_send_sync_msg(hba,
2069175942Sscottl			IOPMU_INBOUND_MSG0_START_BACKGROUND_TASK, 5000)) {
2070175942Sscottl		device_printf(dev, "fail to start background task\n");
2071175942Sscottl		goto teartown_irq_resource;
2072169412Sscottl	}
2073169412Sscottl
2074175942Sscottl	hba->ops->enable_intr(hba);
2075242086Sdelphij	hba->initialized = 1;
2076175942Sscottl
2077169412Sscottl	hba->ioctl_dev = make_dev(&hptiop_cdevsw, unit,
2078169412Sscottl				UID_ROOT, GID_WHEEL /*GID_OPERATOR*/,
2079169412Sscottl				S_IRUSR | S_IWUSR, "%s%d", driver_name, unit);
2080169412Sscottl
2081169412Sscottl
2082169412Sscottl	return 0;
2083175942Sscottl
2084175942Sscottl
2085175942Sscottlteartown_irq_resource:
2086175942Sscottl	bus_teardown_intr(dev, hba->irq_res, hba->irq_handle);
2087175942Sscottl
2088175942Sscottlfree_irq_resource:
2089175942Sscottl	bus_release_resource(dev, SYS_RES_IRQ, 0, hba->irq_res);
2090175942Sscottl
2091269612Sjhb	hptiop_lock_adapter(hba);
2092175942Sscottlfree_hba_path:
2093175942Sscottl	xpt_free_path(hba->path);
2094175942Sscottl
2095175942Sscottlderegister_xpt_bus:
2096175942Sscottl	xpt_bus_deregister(cam_sim_path(hba->sim));
2097175942Sscottl
2098175942Sscottlfree_cam_sim:
2099175942Sscottl	cam_sim_free(hba->sim, /*free devq*/ TRUE);
2100269612Sjhb	hptiop_unlock_adapter(hba);
2101175942Sscottl
2102175942Sscottlsrb_dmamap_unload:
2103175942Sscottl	if (hba->uncached_ptr)
2104175942Sscottl		bus_dmamap_unload(hba->srb_dmat, hba->srb_dmamap);
2105175942Sscottl
2106175942Sscottlsrb_dmamem_free:
2107175942Sscottl	if (hba->uncached_ptr)
2108175942Sscottl		bus_dmamem_free(hba->srb_dmat,
2109175942Sscottl			hba->uncached_ptr, hba->srb_dmamap);
2110175942Sscottl
2111175942Sscottldestroy_srb_dmat:
2112175942Sscottl	if (hba->srb_dmat)
2113175942Sscottl		bus_dma_tag_destroy(hba->srb_dmat);
2114175942Sscottl
2115175942Sscottldestroy_io_dmat:
2116175942Sscottl	if (hba->io_dmat)
2117175942Sscottl		bus_dma_tag_destroy(hba->io_dmat);
2118175942Sscottl
2119175942Sscottlget_config_failed:
2120242086Sdelphij	hba->ops->internal_memfree(hba);
2121175942Sscottl
2122175942Sscottldestroy_parent_tag:
2123175942Sscottl	if (hba->parent_dmat)
2124175942Sscottl		bus_dma_tag_destroy(hba->parent_dmat);
2125175942Sscottl
2126175942Sscottlrelease_pci_res:
2127175942Sscottl	if (hba->ops->release_pci_res)
2128175942Sscottl		hba->ops->release_pci_res(hba);
2129175942Sscottl
2130175942Sscottl	return ENXIO;
2131169412Sscottl}
2132169412Sscottl
2133169412Sscottlstatic int hptiop_detach(device_t dev)
2134169412Sscottl{
2135169412Sscottl	struct hpt_iop_hba * hba = (struct hpt_iop_hba *)device_get_softc(dev);
2136169412Sscottl	int i;
2137169412Sscottl	int error = EBUSY;
2138169412Sscottl
2139169412Sscottl	hptiop_lock_adapter(hba);
2140175942Sscottl	for (i = 0; i < hba->max_devices; i++)
2141175942Sscottl		if (hptiop_os_query_remove_device(hba, i)) {
2142175942Sscottl			device_printf(dev, "%d file system is busy. id=%d",
2143169412Sscottl						hba->pciunit, i);
2144169412Sscottl			goto out;
2145169412Sscottl		}
2146169412Sscottl
2147169412Sscottl	if ((error = hptiop_shutdown(dev)) != 0)
2148169412Sscottl		goto out;
2149175942Sscottl	if (hptiop_send_sync_msg(hba,
2150175942Sscottl		IOPMU_INBOUND_MSG0_STOP_BACKGROUND_TASK, 60000))
2151169412Sscottl		goto out;
2152269612Sjhb	hptiop_unlock_adapter(hba);
2153169412Sscottl
2154169412Sscottl	hptiop_release_resource(hba);
2155269612Sjhb	return (0);
2156169412Sscottlout:
2157169412Sscottl	hptiop_unlock_adapter(hba);
2158169412Sscottl	return error;
2159169412Sscottl}
2160169412Sscottl
2161169412Sscottlstatic int hptiop_shutdown(device_t dev)
2162169412Sscottl{
2163169412Sscottl	struct hpt_iop_hba * hba = (struct hpt_iop_hba *)device_get_softc(dev);
2164169412Sscottl
2165169412Sscottl	int error = 0;
2166169412Sscottl
2167169412Sscottl	if (hba->flag & HPT_IOCTL_FLAG_OPEN) {
2168175942Sscottl		device_printf(dev, "%d device is busy", hba->pciunit);
2169169412Sscottl		return EBUSY;
2170169412Sscottl	}
2171175942Sscottl
2172175942Sscottl	hba->ops->disable_intr(hba);
2173175942Sscottl
2174175942Sscottl	if (hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_SHUTDOWN, 60000))
2175169412Sscottl		error = EBUSY;
2176169412Sscottl
2177169412Sscottl	return error;
2178169412Sscottl}
2179169412Sscottl
2180169412Sscottlstatic void hptiop_pci_intr(void *arg)
2181169412Sscottl{
2182169412Sscottl	struct hpt_iop_hba * hba = (struct hpt_iop_hba *)arg;
2183169412Sscottl	hptiop_lock_adapter(hba);
2184175942Sscottl	hba->ops->iop_intr(hba);
2185169412Sscottl	hptiop_unlock_adapter(hba);
2186169412Sscottl}
2187169412Sscottl
2188169412Sscottlstatic void hptiop_poll(struct cam_sim *sim)
2189169412Sscottl{
2190269612Sjhb	struct hpt_iop_hba *hba;
2191269612Sjhb
2192269612Sjhb	hba = cam_sim_softc(sim);
2193269612Sjhb	hba->ops->iop_intr(hba);
2194169412Sscottl}
2195169412Sscottl
2196169412Sscottlstatic void hptiop_async(void * callback_arg, u_int32_t code,
2197169412Sscottl					struct cam_path * path, void * arg)
2198169412Sscottl{
2199169412Sscottl}
2200169412Sscottl
2201175942Sscottlstatic void hptiop_enable_intr_itl(struct hpt_iop_hba *hba)
2202169412Sscottl{
2203175942Sscottl	BUS_SPACE_WRT4_ITL(outbound_intmask,
2204169412Sscottl		~(IOPMU_OUTBOUND_INT_POSTQUEUE | IOPMU_OUTBOUND_INT_MSG0));
2205169412Sscottl}
2206169412Sscottl
2207175942Sscottlstatic void hptiop_enable_intr_mv(struct hpt_iop_hba *hba)
2208169412Sscottl{
2209169412Sscottl	u_int32_t int_mask;
2210169412Sscottl
2211175942Sscottl	int_mask = BUS_SPACE_RD4_MV0(outbound_intmask);
2212175942Sscottl
2213175942Sscottl	int_mask |= MVIOP_MU_OUTBOUND_INT_POSTQUEUE
2214175942Sscottl			| MVIOP_MU_OUTBOUND_INT_MSG;
2215175942Sscottl    	BUS_SPACE_WRT4_MV0(outbound_intmask,int_mask);
2216169412Sscottl}
2217169412Sscottl
2218242086Sdelphijstatic void hptiop_enable_intr_mvfrey(struct hpt_iop_hba *hba)
2219242086Sdelphij{
2220242086Sdelphij	BUS_SPACE_WRT4_MVFREY2(f0_doorbell_enable, CPU_TO_F0_DRBL_MSG_A_BIT);
2221242086Sdelphij	BUS_SPACE_RD4_MVFREY2(f0_doorbell_enable);
2222242086Sdelphij
2223242086Sdelphij	BUS_SPACE_WRT4_MVFREY2(isr_enable, 0x1);
2224242086Sdelphij	BUS_SPACE_RD4_MVFREY2(isr_enable);
2225242086Sdelphij
2226242086Sdelphij	BUS_SPACE_WRT4_MVFREY2(pcie_f0_int_enable, 0x1010);
2227242086Sdelphij	BUS_SPACE_RD4_MVFREY2(pcie_f0_int_enable);
2228242086Sdelphij}
2229242086Sdelphij
2230175942Sscottlstatic void hptiop_disable_intr_itl(struct hpt_iop_hba *hba)
2231175942Sscottl{
2232175942Sscottl	u_int32_t int_mask;
2233175942Sscottl
2234175942Sscottl	int_mask = BUS_SPACE_RD4_ITL(outbound_intmask);
2235175942Sscottl
2236175942Sscottl	int_mask |= IOPMU_OUTBOUND_INT_POSTQUEUE | IOPMU_OUTBOUND_INT_MSG0;
2237175942Sscottl	BUS_SPACE_WRT4_ITL(outbound_intmask, int_mask);
2238175942Sscottl	BUS_SPACE_RD4_ITL(outbound_intstatus);
2239175942Sscottl}
2240175942Sscottl
2241175942Sscottlstatic void hptiop_disable_intr_mv(struct hpt_iop_hba *hba)
2242175942Sscottl{
2243175942Sscottl	u_int32_t int_mask;
2244175942Sscottl	int_mask = BUS_SPACE_RD4_MV0(outbound_intmask);
2245175942Sscottl
2246175942Sscottl	int_mask &= ~(MVIOP_MU_OUTBOUND_INT_MSG
2247175942Sscottl			| MVIOP_MU_OUTBOUND_INT_POSTQUEUE);
2248175942Sscottl	BUS_SPACE_WRT4_MV0(outbound_intmask,int_mask);
2249175942Sscottl	BUS_SPACE_RD4_MV0(outbound_intmask);
2250175942Sscottl}
2251175942Sscottl
2252242086Sdelphijstatic void hptiop_disable_intr_mvfrey(struct hpt_iop_hba *hba)
2253169412Sscottl{
2254242086Sdelphij	BUS_SPACE_WRT4_MVFREY2(f0_doorbell_enable, 0);
2255242086Sdelphij	BUS_SPACE_RD4_MVFREY2(f0_doorbell_enable);
2256242086Sdelphij
2257242086Sdelphij	BUS_SPACE_WRT4_MVFREY2(isr_enable, 0);
2258242086Sdelphij	BUS_SPACE_RD4_MVFREY2(isr_enable);
2259242086Sdelphij
2260242086Sdelphij	BUS_SPACE_WRT4_MVFREY2(pcie_f0_int_enable, 0);
2261242086Sdelphij	BUS_SPACE_RD4_MVFREY2(pcie_f0_int_enable);
2262169412Sscottl}
2263169412Sscottl
2264242086Sdelphijstatic void hptiop_reset_adapter(void *argv)
2265242086Sdelphij{
2266242086Sdelphij	struct hpt_iop_hba * hba = (struct hpt_iop_hba *)argv;
2267242086Sdelphij	if (hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_RESET, 60000))
2268242086Sdelphij		return;
2269242086Sdelphij	hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_START_BACKGROUND_TASK, 5000);
2270242086Sdelphij}
2271242086Sdelphij
2272169412Sscottlstatic void *hptiop_get_srb(struct hpt_iop_hba * hba)
2273169412Sscottl{
2274169412Sscottl	struct hpt_iop_srb * srb;
2275169412Sscottl
2276169412Sscottl	if (hba->srb_list) {
2277169412Sscottl		srb = hba->srb_list;
2278169412Sscottl		hba->srb_list = srb->next;
2279175942Sscottl		return srb;
2280169412Sscottl	}
2281169412Sscottl
2282175942Sscottl	return NULL;
2283169412Sscottl}
2284169412Sscottl
2285175942Sscottlstatic void hptiop_free_srb(struct hpt_iop_hba *hba, struct hpt_iop_srb *srb)
2286169412Sscottl{
2287169412Sscottl	srb->next = hba->srb_list;
2288169412Sscottl	hba->srb_list = srb;
2289169412Sscottl}
2290169412Sscottl
2291169412Sscottlstatic void hptiop_action(struct cam_sim *sim, union ccb *ccb)
2292169412Sscottl{
2293169412Sscottl	struct hpt_iop_hba * hba = (struct hpt_iop_hba *)cam_sim_softc(sim);
2294169412Sscottl	struct hpt_iop_srb * srb;
2295246713Skib	int error;
2296169412Sscottl
2297169412Sscottl	switch (ccb->ccb_h.func_code) {
2298169412Sscottl
2299169412Sscottl	case XPT_SCSI_IO:
2300169412Sscottl		if (ccb->ccb_h.target_lun != 0 ||
2301175942Sscottl			ccb->ccb_h.target_id >= hba->max_devices ||
2302169412Sscottl			(ccb->ccb_h.flags & CAM_CDB_PHYS))
2303169412Sscottl		{
2304169412Sscottl			ccb->ccb_h.status = CAM_TID_INVALID;
2305169412Sscottl			xpt_done(ccb);
2306269612Sjhb			return;
2307169412Sscottl		}
2308169412Sscottl
2309169412Sscottl		if ((srb = hptiop_get_srb(hba)) == NULL) {
2310175942Sscottl			device_printf(hba->pcidev, "srb allocated failed");
2311169412Sscottl			ccb->ccb_h.status = CAM_REQ_CMP_ERR;
2312169412Sscottl			xpt_done(ccb);
2313269612Sjhb			return;
2314169412Sscottl		}
2315169412Sscottl
2316169412Sscottl		srb->ccb = ccb;
2317246713Skib		error = bus_dmamap_load_ccb(hba->io_dmat,
2318246713Skib					    srb->dma_map,
2319246713Skib					    ccb,
2320246713Skib					    hptiop_post_scsi_command,
2321246713Skib					    srb,
2322246713Skib					    0);
2323169412Sscottl
2324246713Skib		if (error && error != EINPROGRESS) {
2325246713Skib			device_printf(hba->pcidev,
2326246713Skib				"%d bus_dmamap_load error %d",
2327246713Skib				hba->pciunit, error);
2328246713Skib			xpt_freeze_simq(hba->sim, 1);
2329246713Skib			ccb->ccb_h.status = CAM_REQ_CMP_ERR;
2330246713Skib			hptiop_free_srb(hba, srb);
2331246713Skib			xpt_done(ccb);
2332269612Sjhb			return;
2333169412Sscottl		}
2334169412Sscottl
2335169412Sscottl		return;
2336169412Sscottl
2337169412Sscottl	case XPT_RESET_BUS:
2338175942Sscottl		device_printf(hba->pcidev, "reset adapter");
2339169412Sscottl		hba->msg_done = 0;
2340169412Sscottl		hptiop_reset_adapter(hba);
2341169412Sscottl		break;
2342169412Sscottl
2343169412Sscottl	case XPT_GET_TRAN_SETTINGS:
2344169412Sscottl	case XPT_SET_TRAN_SETTINGS:
2345169412Sscottl		ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
2346169412Sscottl		break;
2347169412Sscottl
2348169412Sscottl	case XPT_CALC_GEOMETRY:
2349227912Smarius		cam_calc_geometry(&ccb->ccg, 1);
2350169412Sscottl		break;
2351169412Sscottl
2352169412Sscottl	case XPT_PATH_INQ:
2353169412Sscottl	{
2354169412Sscottl		struct ccb_pathinq *cpi = &ccb->cpi;
2355169412Sscottl
2356169412Sscottl		cpi->version_num = 1;
2357169412Sscottl		cpi->hba_inquiry = PI_SDTR_ABLE;
2358169412Sscottl		cpi->target_sprt = 0;
2359169412Sscottl		cpi->hba_misc = PIM_NOBUSRESET;
2360169412Sscottl		cpi->hba_eng_cnt = 0;
2361175942Sscottl		cpi->max_target = hba->max_devices;
2362169412Sscottl		cpi->max_lun = 0;
2363169412Sscottl		cpi->unit_number = cam_sim_unit(sim);
2364169412Sscottl		cpi->bus_id = cam_sim_bus(sim);
2365175942Sscottl		cpi->initiator_id = hba->max_devices;
2366169412Sscottl		cpi->base_transfer_speed = 3300;
2367169412Sscottl
2368315812Smav		strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
2369315812Smav		strlcpy(cpi->hba_vid, "HPT   ", HBA_IDLEN);
2370315812Smav		strlcpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
2371209340Smav		cpi->transport = XPORT_SPI;
2372209340Smav		cpi->transport_version = 2;
2373209340Smav		cpi->protocol = PROTO_SCSI;
2374209340Smav		cpi->protocol_version = SCSI_REV_2;
2375169412Sscottl		cpi->ccb_h.status = CAM_REQ_CMP;
2376169412Sscottl		break;
2377169412Sscottl	}
2378169412Sscottl
2379169412Sscottl	default:
2380169412Sscottl		ccb->ccb_h.status = CAM_REQ_INVALID;
2381169412Sscottl		break;
2382169412Sscottl	}
2383169412Sscottl
2384169412Sscottl	xpt_done(ccb);
2385169412Sscottl	return;
2386169412Sscottl}
2387169412Sscottl
2388175942Sscottlstatic void hptiop_post_req_itl(struct hpt_iop_hba *hba,
2389175942Sscottl				struct hpt_iop_srb *srb,
2390175942Sscottl				bus_dma_segment_t *segs, int nsegs)
2391169412Sscottl{
2392169412Sscottl	int idx;
2393169412Sscottl	union ccb *ccb = srb->ccb;
2394169412Sscottl	u_int8_t *cdb;
2395169412Sscottl
2396175942Sscottl	if (ccb->ccb_h.flags & CAM_CDB_POINTER)
2397175942Sscottl		cdb = ccb->csio.cdb_io.cdb_ptr;
2398175942Sscottl	else
2399175942Sscottl		cdb = ccb->csio.cdb_io.cdb_bytes;
2400169412Sscottl
2401175942Sscottl	KdPrint(("ccb=%p %x-%x-%x\n",
2402175942Sscottl		ccb, *(u_int32_t *)cdb, *((u_int32_t *)cdb+1), *((u_int32_t *)cdb+2)));
2403169412Sscottl
2404169412Sscottl	if (srb->srb_flag & HPT_SRB_FLAG_HIGH_MEM_ACESS) {
2405175942Sscottl		u_int32_t iop_req32;
2406175942Sscottl		struct hpt_iop_request_scsi_command req;
2407169412Sscottl
2408175942Sscottl		iop_req32 = BUS_SPACE_RD4_ITL(inbound_queue);
2409175942Sscottl
2410175942Sscottl		if (iop_req32 == IOPMU_QUEUE_EMPTY) {
2411298931Spfg			device_printf(hba->pcidev, "invalid req offset\n");
2412175942Sscottl			ccb->ccb_h.status = CAM_BUSY;
2413175942Sscottl			bus_dmamap_unload(hba->io_dmat, srb->dma_map);
2414175942Sscottl			hptiop_free_srb(hba, srb);
2415175942Sscottl			xpt_done(ccb);
2416175942Sscottl			return;
2417169412Sscottl		}
2418175942Sscottl
2419175942Sscottl		if (ccb->csio.dxfer_len && nsegs > 0) {
2420175942Sscottl			struct hpt_iopsg *psg = req.sg_list;
2421175942Sscottl			for (idx = 0; idx < nsegs; idx++, psg++) {
2422175942Sscottl				psg->pci_address = (u_int64_t)segs[idx].ds_addr;
2423175942Sscottl				psg->size = segs[idx].ds_len;
2424175942Sscottl				psg->eot = 0;
2425175942Sscottl			}
2426175942Sscottl			psg[-1].eot = 1;
2427175942Sscottl		}
2428175942Sscottl
2429175942Sscottl		bcopy(cdb, req.cdb, ccb->csio.cdb_len);
2430175942Sscottl
2431242086Sdelphij		req.header.size =
2432242086Sdelphij				offsetof(struct hpt_iop_request_scsi_command, sg_list)
2433175942Sscottl				+ nsegs*sizeof(struct hpt_iopsg);
2434175942Sscottl		req.header.type = IOP_REQUEST_TYPE_SCSI_COMMAND;
2435175942Sscottl		req.header.flags = 0;
2436175942Sscottl		req.header.result = IOP_RESULT_PENDING;
2437175942Sscottl		req.header.context = (u_int64_t)(unsigned long)srb;
2438175942Sscottl		req.dataxfer_length = ccb->csio.dxfer_len;
2439175942Sscottl		req.channel =  0;
2440175942Sscottl		req.target =  ccb->ccb_h.target_id;
2441175942Sscottl		req.lun =  ccb->ccb_h.target_lun;
2442175942Sscottl
2443175942Sscottl		bus_space_write_region_1(hba->bar0t, hba->bar0h, iop_req32,
2444175942Sscottl			(u_int8_t *)&req, req.header.size);
2445175942Sscottl
2446175942Sscottl		if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
2447175942Sscottl			bus_dmamap_sync(hba->io_dmat,
2448175942Sscottl				srb->dma_map, BUS_DMASYNC_PREREAD);
2449175942Sscottl		}
2450175942Sscottl		else if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT)
2451175942Sscottl			bus_dmamap_sync(hba->io_dmat,
2452175942Sscottl				srb->dma_map, BUS_DMASYNC_PREWRITE);
2453175942Sscottl
2454175942Sscottl		BUS_SPACE_WRT4_ITL(inbound_queue,iop_req32);
2455175942Sscottl	} else {
2456175942Sscottl		struct hpt_iop_request_scsi_command *req;
2457175942Sscottl
2458169412Sscottl		req = (struct hpt_iop_request_scsi_command *)srb;
2459175942Sscottl		if (ccb->csio.dxfer_len && nsegs > 0) {
2460175942Sscottl			struct hpt_iopsg *psg = req->sg_list;
2461175942Sscottl			for (idx = 0; idx < nsegs; idx++, psg++) {
2462175942Sscottl				psg->pci_address =
2463175942Sscottl					(u_int64_t)segs[idx].ds_addr;
2464175942Sscottl				psg->size = segs[idx].ds_len;
2465175942Sscottl				psg->eot = 0;
2466175942Sscottl			}
2467175942Sscottl			psg[-1].eot = 1;
2468175942Sscottl		}
2469169412Sscottl
2470175942Sscottl		bcopy(cdb, req->cdb, ccb->csio.cdb_len);
2471175942Sscottl
2472175942Sscottl		req->header.type = IOP_REQUEST_TYPE_SCSI_COMMAND;
2473175942Sscottl		req->header.result = IOP_RESULT_PENDING;
2474175942Sscottl		req->dataxfer_length = ccb->csio.dxfer_len;
2475175942Sscottl		req->channel =  0;
2476175942Sscottl		req->target =  ccb->ccb_h.target_id;
2477175942Sscottl		req->lun =  ccb->ccb_h.target_lun;
2478242086Sdelphij		req->header.size =
2479242086Sdelphij			offsetof(struct hpt_iop_request_scsi_command, sg_list)
2480175942Sscottl			+ nsegs*sizeof(struct hpt_iopsg);
2481175942Sscottl		req->header.context = (u_int64_t)srb->index |
2482175942Sscottl						IOPMU_QUEUE_ADDR_HOST_BIT;
2483175942Sscottl		req->header.flags = IOP_REQUEST_FLAG_OUTPUT_CONTEXT;
2484175942Sscottl
2485175942Sscottl		if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
2486175942Sscottl			bus_dmamap_sync(hba->io_dmat,
2487175942Sscottl				srb->dma_map, BUS_DMASYNC_PREREAD);
2488175942Sscottl		}else if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) {
2489175942Sscottl			bus_dmamap_sync(hba->io_dmat,
2490175942Sscottl				srb->dma_map, BUS_DMASYNC_PREWRITE);
2491175942Sscottl		}
2492175942Sscottl
2493175942Sscottl		if (hba->firmware_version > 0x01020000
2494175942Sscottl			|| hba->interface_version > 0x01020000) {
2495175942Sscottl			u_int32_t size_bits;
2496175942Sscottl
2497175942Sscottl			if (req->header.size < 256)
2498175942Sscottl				size_bits = IOPMU_QUEUE_REQUEST_SIZE_BIT;
2499175942Sscottl			else if (req->header.size < 512)
2500175942Sscottl				size_bits = IOPMU_QUEUE_ADDR_HOST_BIT;
2501175942Sscottl			else
2502175942Sscottl				size_bits = IOPMU_QUEUE_REQUEST_SIZE_BIT
2503175942Sscottl						| IOPMU_QUEUE_ADDR_HOST_BIT;
2504175942Sscottl
2505175942Sscottl			BUS_SPACE_WRT4_ITL(inbound_queue,
2506175942Sscottl				(u_int32_t)srb->phy_addr | size_bits);
2507175942Sscottl		} else
2508175942Sscottl			BUS_SPACE_WRT4_ITL(inbound_queue, (u_int32_t)srb->phy_addr
2509175942Sscottl				|IOPMU_QUEUE_ADDR_HOST_BIT);
2510175942Sscottl	}
2511175942Sscottl}
2512175942Sscottl
2513175942Sscottlstatic void hptiop_post_req_mv(struct hpt_iop_hba *hba,
2514175942Sscottl				struct hpt_iop_srb *srb,
2515175942Sscottl				bus_dma_segment_t *segs, int nsegs)
2516175942Sscottl{
2517175942Sscottl	int idx, size;
2518175942Sscottl	union ccb *ccb = srb->ccb;
2519175942Sscottl	u_int8_t *cdb;
2520175942Sscottl	struct hpt_iop_request_scsi_command *req;
2521175942Sscottl	u_int64_t req_phy;
2522175942Sscottl
2523175942Sscottl    	req = (struct hpt_iop_request_scsi_command *)srb;
2524175942Sscottl	req_phy = srb->phy_addr;
2525175942Sscottl
2526169412Sscottl	if (ccb->csio.dxfer_len && nsegs > 0) {
2527169412Sscottl		struct hpt_iopsg *psg = req->sg_list;
2528169412Sscottl		for (idx = 0; idx < nsegs; idx++, psg++) {
2529169412Sscottl			psg->pci_address = (u_int64_t)segs[idx].ds_addr;
2530169412Sscottl			psg->size = segs[idx].ds_len;
2531169412Sscottl			psg->eot = 0;
2532169412Sscottl		}
2533169412Sscottl		psg[-1].eot = 1;
2534169412Sscottl	}
2535169412Sscottl	if (ccb->ccb_h.flags & CAM_CDB_POINTER)
2536169412Sscottl		cdb = ccb->csio.cdb_io.cdb_ptr;
2537169412Sscottl	else
2538169412Sscottl		cdb = ccb->csio.cdb_io.cdb_bytes;
2539169412Sscottl
2540169412Sscottl	bcopy(cdb, req->cdb, ccb->csio.cdb_len);
2541169412Sscottl	req->header.type = IOP_REQUEST_TYPE_SCSI_COMMAND;
2542169412Sscottl	req->header.result = IOP_RESULT_PENDING;
2543169412Sscottl	req->dataxfer_length = ccb->csio.dxfer_len;
2544175942Sscottl	req->channel = 0;
2545169412Sscottl	req->target =  ccb->ccb_h.target_id;
2546169412Sscottl	req->lun =  ccb->ccb_h.target_lun;
2547169412Sscottl	req->header.size = sizeof(struct hpt_iop_request_scsi_command)
2548175942Sscottl				- sizeof(struct hpt_iopsg)
2549175942Sscottl				+ nsegs * sizeof(struct hpt_iopsg);
2550169412Sscottl	if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
2551169412Sscottl		bus_dmamap_sync(hba->io_dmat,
2552175942Sscottl			srb->dma_map, BUS_DMASYNC_PREREAD);
2553169412Sscottl	}
2554169412Sscottl	else if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT)
2555169412Sscottl		bus_dmamap_sync(hba->io_dmat,
2556175942Sscottl			srb->dma_map, BUS_DMASYNC_PREWRITE);
2557175942Sscottl	req->header.context = (u_int64_t)srb->index
2558175942Sscottl					<< MVIOP_REQUEST_NUMBER_START_BIT
2559175942Sscottl					| MVIOP_CMD_TYPE_SCSI;
2560175942Sscottl	req->header.flags = IOP_REQUEST_FLAG_OUTPUT_CONTEXT;
2561175942Sscottl	size = req->header.size >> 8;
2562175942Sscottl	hptiop_mv_inbound_write(req_phy
2563175942Sscottl			| MVIOP_MU_QUEUE_ADDR_HOST_BIT
2564299033Saraujo			| imin(3, size), hba);
2565169412Sscottl}
2566169412Sscottl
2567242086Sdelphijstatic void hptiop_post_req_mvfrey(struct hpt_iop_hba *hba,
2568242086Sdelphij				struct hpt_iop_srb *srb,
2569242086Sdelphij				bus_dma_segment_t *segs, int nsegs)
2570242086Sdelphij{
2571242086Sdelphij	int idx, index;
2572242086Sdelphij	union ccb *ccb = srb->ccb;
2573242086Sdelphij	u_int8_t *cdb;
2574242086Sdelphij	struct hpt_iop_request_scsi_command *req;
2575242086Sdelphij	u_int64_t req_phy;
2576242086Sdelphij
2577242086Sdelphij	req = (struct hpt_iop_request_scsi_command *)srb;
2578242086Sdelphij	req_phy = srb->phy_addr;
2579242086Sdelphij
2580242086Sdelphij	if (ccb->csio.dxfer_len && nsegs > 0) {
2581242086Sdelphij		struct hpt_iopsg *psg = req->sg_list;
2582242086Sdelphij		for (idx = 0; idx < nsegs; idx++, psg++) {
2583242086Sdelphij			psg->pci_address = (u_int64_t)segs[idx].ds_addr | 1;
2584242086Sdelphij			psg->size = segs[idx].ds_len;
2585242086Sdelphij			psg->eot = 0;
2586242086Sdelphij		}
2587242086Sdelphij		psg[-1].eot = 1;
2588242086Sdelphij	}
2589242086Sdelphij	if (ccb->ccb_h.flags & CAM_CDB_POINTER)
2590242086Sdelphij		cdb = ccb->csio.cdb_io.cdb_ptr;
2591242086Sdelphij	else
2592242086Sdelphij		cdb = ccb->csio.cdb_io.cdb_bytes;
2593242086Sdelphij
2594242086Sdelphij	bcopy(cdb, req->cdb, ccb->csio.cdb_len);
2595242086Sdelphij	req->header.type = IOP_REQUEST_TYPE_SCSI_COMMAND;
2596242086Sdelphij	req->header.result = IOP_RESULT_PENDING;
2597242086Sdelphij	req->dataxfer_length = ccb->csio.dxfer_len;
2598242086Sdelphij	req->channel = 0;
2599242086Sdelphij	req->target = ccb->ccb_h.target_id;
2600242086Sdelphij	req->lun = ccb->ccb_h.target_lun;
2601242086Sdelphij	req->header.size = sizeof(struct hpt_iop_request_scsi_command)
2602242086Sdelphij				- sizeof(struct hpt_iopsg)
2603242086Sdelphij				+ nsegs * sizeof(struct hpt_iopsg);
2604242086Sdelphij	if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
2605242086Sdelphij		bus_dmamap_sync(hba->io_dmat,
2606242086Sdelphij			srb->dma_map, BUS_DMASYNC_PREREAD);
2607242086Sdelphij	}
2608242086Sdelphij	else if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT)
2609242086Sdelphij		bus_dmamap_sync(hba->io_dmat,
2610242086Sdelphij			srb->dma_map, BUS_DMASYNC_PREWRITE);
2611242086Sdelphij
2612242086Sdelphij	req->header.flags = IOP_REQUEST_FLAG_OUTPUT_CONTEXT
2613242086Sdelphij						| IOP_REQUEST_FLAG_ADDR_BITS
2614242086Sdelphij						| ((req_phy >> 16) & 0xffff0000);
2615242086Sdelphij	req->header.context = ((req_phy & 0xffffffff) << 32 )
2616242086Sdelphij						| srb->index << 4
2617242086Sdelphij						| IOPMU_QUEUE_ADDR_HOST_BIT | req->header.type;
2618242086Sdelphij
2619242086Sdelphij	hba->u.mvfrey.inlist_wptr++;
2620242086Sdelphij	index = hba->u.mvfrey.inlist_wptr & 0x3fff;
2621242086Sdelphij
2622242086Sdelphij	if (index == hba->u.mvfrey.list_count) {
2623242086Sdelphij		index = 0;
2624242086Sdelphij		hba->u.mvfrey.inlist_wptr &= ~0x3fff;
2625242086Sdelphij		hba->u.mvfrey.inlist_wptr ^= CL_POINTER_TOGGLE;
2626242086Sdelphij	}
2627242086Sdelphij
2628242086Sdelphij	hba->u.mvfrey.inlist[index].addr = req_phy;
2629242086Sdelphij	hba->u.mvfrey.inlist[index].intrfc_len = (req->header.size + 3) / 4;
2630242086Sdelphij
2631242086Sdelphij	BUS_SPACE_WRT4_MVFREY2(inbound_write_ptr, hba->u.mvfrey.inlist_wptr);
2632242086Sdelphij	BUS_SPACE_RD4_MVFREY2(inbound_write_ptr);
2633242086Sdelphij
2634242086Sdelphij	if (req->header.type == IOP_REQUEST_TYPE_SCSI_COMMAND) {
2635269612Sjhb		callout_reset(&srb->timeout, 20 * hz, hptiop_reset_adapter, hba);
2636242086Sdelphij	}
2637242086Sdelphij}
2638242086Sdelphij
2639175942Sscottlstatic void hptiop_post_scsi_command(void *arg, bus_dma_segment_t *segs,
2640175942Sscottl					int nsegs, int error)
2641169412Sscottl{
2642175942Sscottl	struct hpt_iop_srb *srb = (struct hpt_iop_srb *)arg;
2643175942Sscottl	union ccb *ccb = srb->ccb;
2644175942Sscottl	struct hpt_iop_hba *hba = srb->hba;
2645169412Sscottl
2646175942Sscottl	if (error || nsegs > hba->max_sg_count) {
2647257381Snwhitehorn		KdPrint(("hptiop: func_code=%x tid=%x lun=%jx nsegs=%d\n",
2648175942Sscottl			ccb->ccb_h.func_code,
2649175942Sscottl			ccb->ccb_h.target_id,
2650257381Snwhitehorn			(uintmax_t)ccb->ccb_h.target_lun, nsegs));
2651175942Sscottl		ccb->ccb_h.status = CAM_BUSY;
2652175942Sscottl		bus_dmamap_unload(hba->io_dmat, srb->dma_map);
2653169412Sscottl		hptiop_free_srb(hba, srb);
2654169412Sscottl		xpt_done(ccb);
2655175942Sscottl		return;
2656169412Sscottl	}
2657175942Sscottl
2658175942Sscottl	hba->ops->post_req(hba, srb, segs, nsegs);
2659169412Sscottl}
2660169412Sscottl
2661175942Sscottlstatic void hptiop_mv_map_ctlcfg(void *arg, bus_dma_segment_t *segs,
2662175942Sscottl				int nsegs, int error)
2663175942Sscottl{
2664175942Sscottl	struct hpt_iop_hba *hba = (struct hpt_iop_hba *)arg;
2665175942Sscottl	hba->ctlcfgcmd_phy = ((u_int64_t)segs->ds_addr + 0x1F)
2666175942Sscottl				& ~(u_int64_t)0x1F;
2667175942Sscottl	hba->ctlcfg_ptr = (u_int8_t *)(((unsigned long)hba->ctlcfg_ptr + 0x1F)
2668175942Sscottl				& ~0x1F);
2669175942Sscottl}
2670175942Sscottl
2671242086Sdelphijstatic void hptiop_mvfrey_map_ctlcfg(void *arg, bus_dma_segment_t *segs,
2672242086Sdelphij				int nsegs, int error)
2673242086Sdelphij{
2674242086Sdelphij	struct hpt_iop_hba *hba = (struct hpt_iop_hba *)arg;
2675242086Sdelphij	char *p;
2676242086Sdelphij	u_int64_t phy;
2677242086Sdelphij	u_int32_t list_count = hba->u.mvfrey.list_count;
2678242086Sdelphij
2679242086Sdelphij	phy = ((u_int64_t)segs->ds_addr + 0x1F)
2680242086Sdelphij				& ~(u_int64_t)0x1F;
2681242086Sdelphij	p = (u_int8_t *)(((unsigned long)hba->ctlcfg_ptr + 0x1F)
2682242086Sdelphij				& ~0x1F);
2683242086Sdelphij
2684242086Sdelphij	hba->ctlcfgcmd_phy = phy;
2685242086Sdelphij	hba->ctlcfg_ptr = p;
2686242086Sdelphij
2687242086Sdelphij	p += 0x800;
2688242086Sdelphij	phy += 0x800;
2689242086Sdelphij
2690242086Sdelphij	hba->u.mvfrey.inlist = (struct mvfrey_inlist_entry *)p;
2691242086Sdelphij	hba->u.mvfrey.inlist_phy = phy;
2692242086Sdelphij
2693242086Sdelphij	p += list_count * sizeof(struct mvfrey_inlist_entry);
2694242086Sdelphij	phy += list_count * sizeof(struct mvfrey_inlist_entry);
2695242086Sdelphij
2696242086Sdelphij	hba->u.mvfrey.outlist = (struct mvfrey_outlist_entry *)p;
2697242086Sdelphij	hba->u.mvfrey.outlist_phy = phy;
2698242086Sdelphij
2699242086Sdelphij	p += list_count * sizeof(struct mvfrey_outlist_entry);
2700242086Sdelphij	phy += list_count * sizeof(struct mvfrey_outlist_entry);
2701242086Sdelphij
2702242086Sdelphij	hba->u.mvfrey.outlist_cptr = (u_int32_t *)p;
2703242086Sdelphij	hba->u.mvfrey.outlist_cptr_phy = phy;
2704242086Sdelphij}
2705242086Sdelphij
2706169412Sscottlstatic void hptiop_map_srb(void *arg, bus_dma_segment_t *segs,
2707175942Sscottl				int nsegs, int error)
2708169412Sscottl{
2709169412Sscottl	struct hpt_iop_hba * hba = (struct hpt_iop_hba *)arg;
2710169412Sscottl	bus_addr_t phy_addr = (segs->ds_addr + 0x1F) & ~(bus_addr_t)0x1F;
2711169412Sscottl	struct hpt_iop_srb *srb, *tmp_srb;
2712169412Sscottl	int i;
2713169412Sscottl
2714169412Sscottl	if (error || nsegs == 0) {
2715175942Sscottl		device_printf(hba->pcidev, "hptiop_map_srb error");
2716169412Sscottl		return;
2717169412Sscottl	}
2718169412Sscottl
2719169412Sscottl	/* map srb */
2720169412Sscottl	srb = (struct hpt_iop_srb *)
2721175942Sscottl		(((unsigned long)hba->uncached_ptr + 0x1F)
2722175942Sscottl		& ~(unsigned long)0x1F);
2723169412Sscottl
2724169412Sscottl	for (i = 0; i < HPT_SRB_MAX_QUEUE_SIZE; i++) {
2725169412Sscottl		tmp_srb = (struct hpt_iop_srb *)
2726169412Sscottl					((char *)srb + i * HPT_SRB_MAX_SIZE);
2727169412Sscottl		if (((unsigned long)tmp_srb & 0x1F) == 0) {
2728169412Sscottl			if (bus_dmamap_create(hba->io_dmat,
2729169412Sscottl						0, &tmp_srb->dma_map)) {
2730175942Sscottl				device_printf(hba->pcidev, "dmamap create failed");
2731169412Sscottl				return;
2732169412Sscottl			}
2733169412Sscottl
2734169412Sscottl			bzero(tmp_srb, sizeof(struct hpt_iop_srb));
2735169412Sscottl			tmp_srb->hba = hba;
2736169412Sscottl			tmp_srb->index = i;
2737175942Sscottl			if (hba->ctlcfg_ptr == 0) {/*itl iop*/
2738175942Sscottl				tmp_srb->phy_addr = (u_int64_t)(u_int32_t)
2739175942Sscottl							(phy_addr >> 5);
2740175942Sscottl				if (phy_addr & IOPMU_MAX_MEM_SUPPORT_MASK_32G)
2741175942Sscottl					tmp_srb->srb_flag =
2742175942Sscottl						HPT_SRB_FLAG_HIGH_MEM_ACESS;
2743175942Sscottl			} else {
2744175942Sscottl				tmp_srb->phy_addr = phy_addr;
2745175942Sscottl			}
2746175942Sscottl
2747269612Sjhb			callout_init_mtx(&tmp_srb->timeout, &hba->lock, 0);
2748169412Sscottl			hptiop_free_srb(hba, tmp_srb);
2749169412Sscottl			hba->srb[i] = tmp_srb;
2750169412Sscottl			phy_addr += HPT_SRB_MAX_SIZE;
2751169412Sscottl		}
2752169412Sscottl		else {
2753175942Sscottl			device_printf(hba->pcidev, "invalid alignment");
2754169412Sscottl			return;
2755169412Sscottl		}
2756169412Sscottl	}
2757169412Sscottl}
2758169412Sscottl
2759175942Sscottlstatic void hptiop_os_message_callback(struct hpt_iop_hba * hba, u_int32_t msg)
2760169412Sscottl{
2761242086Sdelphij	hba->msg_done = 1;
2762169412Sscottl}
2763169412Sscottl
2764175942Sscottlstatic  int hptiop_os_query_remove_device(struct hpt_iop_hba * hba,
2765175942Sscottl						int target_id)
2766169412Sscottl{
2767169412Sscottl	struct cam_periph       *periph = NULL;
2768169412Sscottl	struct cam_path         *path;
2769169412Sscottl	int                     status, retval = 0;
2770169412Sscottl
2771169412Sscottl	status = xpt_create_path(&path, NULL, hba->sim->path_id, target_id, 0);
2772169412Sscottl
2773169412Sscottl	if (status == CAM_REQ_CMP) {
2774169412Sscottl		if ((periph = cam_periph_find(path, "da")) != NULL) {
2775169412Sscottl			if (periph->refcount >= 1) {
2776175942Sscottl				device_printf(hba->pcidev, "%d ,"
2777175942Sscottl					"target_id=0x%x,"
2778175942Sscottl					"refcount=%d",
2779169412Sscottl				    hba->pciunit, target_id, periph->refcount);
2780169412Sscottl				retval = -1;
2781169412Sscottl			}
2782169412Sscottl		}
2783169412Sscottl		xpt_free_path(path);
2784169412Sscottl	}
2785169412Sscottl	return retval;
2786169412Sscottl}
2787169412Sscottl
2788169412Sscottlstatic void hptiop_release_resource(struct hpt_iop_hba *hba)
2789169412Sscottl{
2790175942Sscottl	int i;
2791269612Sjhb
2792269612Sjhb	if (hba->ioctl_dev)
2793269612Sjhb		destroy_dev(hba->ioctl_dev);
2794269612Sjhb
2795175942Sscottl	if (hba->path) {
2796175942Sscottl		struct ccb_setasync ccb;
2797169412Sscottl
2798169412Sscottl		xpt_setup_ccb(&ccb.ccb_h, hba->path, /*priority*/5);
2799169412Sscottl		ccb.ccb_h.func_code = XPT_SASYNC_CB;
2800169412Sscottl		ccb.event_enable = 0;
2801169412Sscottl		ccb.callback = hptiop_async;
2802169412Sscottl		ccb.callback_arg = hba->sim;
2803169412Sscottl		xpt_action((union ccb *)&ccb);
2804169412Sscottl		xpt_free_path(hba->path);
2805169412Sscottl	}
2806169412Sscottl
2807269612Sjhb	if (hba->irq_handle)
2808269612Sjhb		bus_teardown_intr(hba->pcidev, hba->irq_res, hba->irq_handle);
2809269612Sjhb
2810169412Sscottl	if (hba->sim) {
2811269612Sjhb		hptiop_lock_adapter(hba);
2812169412Sscottl		xpt_bus_deregister(cam_sim_path(hba->sim));
2813169412Sscottl		cam_sim_free(hba->sim, TRUE);
2814269612Sjhb		hptiop_unlock_adapter(hba);
2815169412Sscottl	}
2816169412Sscottl
2817175942Sscottl	if (hba->ctlcfg_dmat) {
2818175942Sscottl		bus_dmamap_unload(hba->ctlcfg_dmat, hba->ctlcfg_dmamap);
2819175942Sscottl		bus_dmamem_free(hba->ctlcfg_dmat,
2820175942Sscottl					hba->ctlcfg_ptr, hba->ctlcfg_dmamap);
2821175942Sscottl		bus_dma_tag_destroy(hba->ctlcfg_dmat);
2822175942Sscottl	}
2823175942Sscottl
2824175942Sscottl	for (i = 0; i < HPT_SRB_MAX_QUEUE_SIZE; i++) {
2825175942Sscottl		struct hpt_iop_srb *srb = hba->srb[i];
2826175942Sscottl		if (srb->dma_map)
2827175942Sscottl			bus_dmamap_destroy(hba->io_dmat, srb->dma_map);
2828269612Sjhb		callout_drain(&srb->timeout);
2829175942Sscottl	}
2830175942Sscottl
2831169412Sscottl	if (hba->srb_dmat) {
2832169412Sscottl		bus_dmamap_unload(hba->srb_dmat, hba->srb_dmamap);
2833175942Sscottl		bus_dmamap_destroy(hba->srb_dmat, hba->srb_dmamap);
2834169412Sscottl		bus_dma_tag_destroy(hba->srb_dmat);
2835169412Sscottl	}
2836169412Sscottl
2837169412Sscottl	if (hba->io_dmat)
2838169412Sscottl		bus_dma_tag_destroy(hba->io_dmat);
2839169412Sscottl
2840169412Sscottl	if (hba->parent_dmat)
2841169412Sscottl		bus_dma_tag_destroy(hba->parent_dmat);
2842169412Sscottl
2843169412Sscottl	if (hba->irq_res)
2844175942Sscottl		bus_release_resource(hba->pcidev, SYS_RES_IRQ,
2845175942Sscottl					0, hba->irq_res);
2846169412Sscottl
2847169412Sscottl	if (hba->bar0_res)
2848169412Sscottl		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
2849169412Sscottl					hba->bar0_rid, hba->bar0_res);
2850175942Sscottl	if (hba->bar2_res)
2851175942Sscottl		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
2852175942Sscottl					hba->bar2_rid, hba->bar2_res);
2853269612Sjhb	mtx_destroy(&hba->lock);
2854169412Sscottl}
2855