hptiop.c revision 203108
1169412Sscottl/*
2175942Sscottl * HighPoint RR3xxx/4xxx RAID Driver for FreeBSD
3175942Sscottl * Copyright (C) 2007-2008 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: head/sys/dev/hptiop/hptiop.c 203108 2010-01-28 08:41:30Z mav $");
29169412Sscottl
30169412Sscottl#include <sys/param.h>
31169412Sscottl#include <sys/types.h>
32169412Sscottl#include <sys/cons.h>
33169412Sscottl#if (__FreeBSD_version >= 500000)
34169412Sscottl#include <sys/time.h>
35169412Sscottl#include <sys/systm.h>
36169412Sscottl#else
37169412Sscottl#include <machine/clock.h>
38169412Sscottl#endif
39169412Sscottl
40169412Sscottl#include <sys/stat.h>
41169412Sscottl#include <sys/malloc.h>
42169412Sscottl#include <sys/conf.h>
43169412Sscottl#include <sys/libkern.h>
44169412Sscottl#include <sys/kernel.h>
45169412Sscottl
46169412Sscottl#if (__FreeBSD_version >= 500000)
47169412Sscottl#include <sys/kthread.h>
48169412Sscottl#include <sys/mutex.h>
49169412Sscottl#include <sys/module.h>
50169412Sscottl#endif
51169412Sscottl
52169412Sscottl#include <sys/eventhandler.h>
53169412Sscottl#include <sys/bus.h>
54169412Sscottl#include <sys/taskqueue.h>
55169412Sscottl#include <sys/ioccom.h>
56169412Sscottl
57169412Sscottl#include <machine/resource.h>
58169412Sscottl#include <machine/bus.h>
59169412Sscottl#include <machine/stdarg.h>
60169412Sscottl#include <sys/rman.h>
61169412Sscottl
62169412Sscottl#include <vm/vm.h>
63169412Sscottl#include <vm/pmap.h>
64169412Sscottl
65169412Sscottl#if (__FreeBSD_version >= 500000)
66169412Sscottl#include <dev/pci/pcireg.h>
67169412Sscottl#include <dev/pci/pcivar.h>
68169412Sscottl#else
69169412Sscottl#include <pci/pcivar.h>
70169412Sscottl#include <pci/pcireg.h>
71169412Sscottl#endif
72169412Sscottl
73169412Sscottl#if (__FreeBSD_version <= 500043)
74169412Sscottl#include <sys/devicestat.h>
75169412Sscottl#endif
76169412Sscottl
77169412Sscottl#include <cam/cam.h>
78169412Sscottl#include <cam/cam_ccb.h>
79169412Sscottl#include <cam/cam_sim.h>
80169412Sscottl#include <cam/cam_xpt_sim.h>
81169412Sscottl#include <cam/cam_debug.h>
82169412Sscottl#include <cam/cam_periph.h>
83169412Sscottl#include <cam/scsi/scsi_all.h>
84169412Sscottl#include <cam/scsi/scsi_message.h>
85169412Sscottl
86169412Sscottl#if (__FreeBSD_version < 500043)
87169412Sscottl#include <sys/bus_private.h>
88169412Sscottl#endif
89169412Sscottl
90169412Sscottl#include <dev/hptiop/hptiop.h>
91169412Sscottl
92169412Sscottlstatic char driver_name[] = "hptiop";
93175942Sscottlstatic char driver_version[] = "v1.3 (010208)";
94169412Sscottl
95169412Sscottlstatic devclass_t hptiop_devclass;
96169412Sscottl
97175942Sscottlstatic int hptiop_send_sync_msg(struct hpt_iop_hba *hba,
98175942Sscottl				u_int32_t msg, u_int32_t millisec);
99175942Sscottlstatic void hptiop_request_callback_itl(struct hpt_iop_hba *hba,
100175942Sscottl							u_int32_t req);
101175942Sscottlstatic void hptiop_request_callback_mv(struct hpt_iop_hba *hba, u_int64_t req);
102175942Sscottlstatic void hptiop_os_message_callback(struct hpt_iop_hba *hba, u_int32_t msg);
103175942Sscottlstatic int  hptiop_do_ioctl_itl(struct hpt_iop_hba *hba,
104175942Sscottl				struct hpt_iop_ioctl_param *pParams);
105175942Sscottlstatic int  hptiop_do_ioctl_mv(struct hpt_iop_hba *hba,
106175942Sscottl				struct hpt_iop_ioctl_param *pParams);
107175942Sscottlstatic int  hptiop_rescan_bus(struct hpt_iop_hba *hba);
108175942Sscottlstatic int hptiop_alloc_pci_res_itl(struct hpt_iop_hba *hba);
109175942Sscottlstatic int hptiop_alloc_pci_res_mv(struct hpt_iop_hba *hba);
110175942Sscottlstatic int hptiop_get_config_itl(struct hpt_iop_hba *hba,
111175942Sscottl				struct hpt_iop_request_get_config *config);
112175942Sscottlstatic int hptiop_get_config_mv(struct hpt_iop_hba *hba,
113175942Sscottl				struct hpt_iop_request_get_config *config);
114175942Sscottlstatic int hptiop_set_config_itl(struct hpt_iop_hba *hba,
115175942Sscottl				struct hpt_iop_request_set_config *config);
116175942Sscottlstatic int hptiop_set_config_mv(struct hpt_iop_hba *hba,
117175942Sscottl				struct hpt_iop_request_set_config *config);
118175942Sscottlstatic int hptiop_internal_memalloc_mv(struct hpt_iop_hba *hba);
119175942Sscottlstatic int hptiop_internal_memfree_mv(struct hpt_iop_hba *hba);
120175942Sscottlstatic int  hptiop_post_ioctl_command_itl(struct hpt_iop_hba *hba,
121175942Sscottl			u_int32_t req32, struct hpt_iop_ioctl_param *pParams);
122175942Sscottlstatic int  hptiop_post_ioctl_command_mv(struct hpt_iop_hba *hba,
123175942Sscottl				struct hpt_iop_request_ioctl_command *req,
124175942Sscottl				struct hpt_iop_ioctl_param *pParams);
125175942Sscottlstatic void hptiop_post_req_itl(struct hpt_iop_hba *hba,
126175942Sscottl				struct hpt_iop_srb *srb,
127175942Sscottl				bus_dma_segment_t *segs, int nsegs);
128175942Sscottlstatic void hptiop_post_req_mv(struct hpt_iop_hba *hba,
129175942Sscottl				struct hpt_iop_srb *srb,
130175942Sscottl				bus_dma_segment_t *segs, int nsegs);
131175942Sscottlstatic void hptiop_post_msg_itl(struct hpt_iop_hba *hba, u_int32_t msg);
132175942Sscottlstatic void hptiop_post_msg_mv(struct hpt_iop_hba *hba, u_int32_t msg);
133175942Sscottlstatic void hptiop_enable_intr_itl(struct hpt_iop_hba *hba);
134175942Sscottlstatic void hptiop_enable_intr_mv(struct hpt_iop_hba *hba);
135175942Sscottlstatic void hptiop_disable_intr_itl(struct hpt_iop_hba *hba);
136175942Sscottlstatic void hptiop_disable_intr_mv(struct hpt_iop_hba *hba);
137175942Sscottlstatic void hptiop_free_srb(struct hpt_iop_hba *hba, struct hpt_iop_srb *srb);
138175942Sscottlstatic int  hptiop_os_query_remove_device(struct hpt_iop_hba *hba, int tid);
139169412Sscottlstatic int  hptiop_probe(device_t dev);
140169412Sscottlstatic int  hptiop_attach(device_t dev);
141169412Sscottlstatic int  hptiop_detach(device_t dev);
142169412Sscottlstatic int  hptiop_shutdown(device_t dev);
143169412Sscottlstatic void hptiop_action(struct cam_sim *sim, union ccb *ccb);
144169412Sscottlstatic void hptiop_poll(struct cam_sim *sim);
145175942Sscottlstatic void hptiop_async(void *callback_arg, u_int32_t code,
146175942Sscottl					struct cam_path *path, void *arg);
147169412Sscottlstatic void hptiop_pci_intr(void *arg);
148175942Sscottlstatic void hptiop_release_resource(struct hpt_iop_hba *hba);
149175942Sscottlstatic int  hptiop_reset_adapter(struct hpt_iop_hba *hba);
150169412Sscottl
151169412Sscottlstatic d_open_t hptiop_open;
152169412Sscottlstatic d_close_t hptiop_close;
153169412Sscottlstatic d_ioctl_t hptiop_ioctl;
154169412Sscottl
155169412Sscottlstatic struct cdevsw hptiop_cdevsw = {
156169412Sscottl	.d_open = hptiop_open,
157169412Sscottl	.d_close = hptiop_close,
158169412Sscottl	.d_ioctl = hptiop_ioctl,
159169412Sscottl	.d_name = driver_name,
160169412Sscottl#if __FreeBSD_version>=503000
161169412Sscottl	.d_version = D_VERSION,
162169412Sscottl#endif
163169412Sscottl#if (__FreeBSD_version>=503000 && __FreeBSD_version<600034)
164169412Sscottl	.d_flags = D_NEEDGIANT,
165169412Sscottl#endif
166169412Sscottl#if __FreeBSD_version<600034
167169412Sscottl#if __FreeBSD_version>=501000
168169412Sscottl	.d_maj = MAJOR_AUTO,
169169412Sscottl#else
170169412Sscottl	.d_maj = HPT_DEV_MAJOR,
171169412Sscottl#endif
172169412Sscottl#endif
173169412Sscottl};
174169412Sscottl
175169412Sscottl#if __FreeBSD_version < 503000
176169412Sscottl#define hba_from_dev(dev) ((struct hpt_iop_hba *)(dev)->si_drv1)
177169412Sscottl#else
178169412Sscottl#define hba_from_dev(dev) \
179183397Sed	((struct hpt_iop_hba *)devclass_get_softc(hptiop_devclass, dev2unit(dev)))
180169412Sscottl#endif
181169412Sscottl
182175942Sscottl#define BUS_SPACE_WRT4_ITL(offset, value) bus_space_write_4(hba->bar0t,\
183175942Sscottl		hba->bar0h, offsetof(struct hpt_iopmu_itl, offset), (value))
184175942Sscottl#define BUS_SPACE_RD4_ITL(offset) bus_space_read_4(hba->bar0t,\
185175942Sscottl		hba->bar0h, offsetof(struct hpt_iopmu_itl, offset))
186175942Sscottl
187175942Sscottl#define BUS_SPACE_WRT4_MV0(offset, value) bus_space_write_4(hba->bar0t,\
188175942Sscottl		hba->bar0h, offsetof(struct hpt_iopmv_regs, offset), value)
189175942Sscottl#define BUS_SPACE_RD4_MV0(offset) bus_space_read_4(hba->bar0t,\
190175942Sscottl		hba->bar0h, offsetof(struct hpt_iopmv_regs, offset))
191175942Sscottl#define BUS_SPACE_WRT4_MV2(offset, value) bus_space_write_4(hba->bar2t,\
192175942Sscottl		hba->bar2h, offsetof(struct hpt_iopmu_mv, offset), value)
193175942Sscottl#define BUS_SPACE_RD4_MV2(offset) bus_space_read_4(hba->bar2t,\
194175942Sscottl		hba->bar2h, offsetof(struct hpt_iopmu_mv, offset))
195175942Sscottl
196169412Sscottlstatic int hptiop_open(ioctl_dev_t dev, int flags,
197169412Sscottl					int devtype, ioctl_thread_t proc)
198169412Sscottl{
199175942Sscottl	struct hpt_iop_hba *hba = hba_from_dev(dev);
200169412Sscottl
201169412Sscottl	if (hba==NULL)
202169412Sscottl		return ENXIO;
203169412Sscottl	if (hba->flag & HPT_IOCTL_FLAG_OPEN)
204169412Sscottl		return EBUSY;
205169412Sscottl	hba->flag |= HPT_IOCTL_FLAG_OPEN;
206169412Sscottl	return 0;
207169412Sscottl}
208169412Sscottl
209169412Sscottlstatic int hptiop_close(ioctl_dev_t dev, int flags,
210169412Sscottl					int devtype, ioctl_thread_t proc)
211169412Sscottl{
212175942Sscottl	struct hpt_iop_hba *hba = hba_from_dev(dev);
213169412Sscottl	hba->flag &= ~(u_int32_t)HPT_IOCTL_FLAG_OPEN;
214169412Sscottl	return 0;
215169412Sscottl}
216169412Sscottl
217169412Sscottlstatic int hptiop_ioctl(ioctl_dev_t dev, u_long cmd, caddr_t data,
218169412Sscottl					int flags, ioctl_thread_t proc)
219169412Sscottl{
220169412Sscottl	int ret = EFAULT;
221175942Sscottl	struct hpt_iop_hba *hba = hba_from_dev(dev);
222169412Sscottl
223169412Sscottl#if (__FreeBSD_version >= 500000)
224169412Sscottl	mtx_lock(&Giant);
225169412Sscottl#endif
226169412Sscottl
227169412Sscottl	switch (cmd) {
228169412Sscottl	case HPT_DO_IOCONTROL:
229175942Sscottl		ret = hba->ops->do_ioctl(hba,
230175942Sscottl				(struct hpt_iop_ioctl_param *)data);
231169412Sscottl		break;
232169412Sscottl	case HPT_SCAN_BUS:
233169412Sscottl		ret = hptiop_rescan_bus(hba);
234169412Sscottl		break;
235169412Sscottl	}
236169412Sscottl
237169412Sscottl#if (__FreeBSD_version >= 500000)
238169412Sscottl	mtx_unlock(&Giant);
239169412Sscottl#endif
240169412Sscottl
241169412Sscottl	return ret;
242169412Sscottl}
243169412Sscottl
244175942Sscottlstatic u_int64_t hptiop_mv_outbound_read(struct hpt_iop_hba *hba)
245169412Sscottl{
246175942Sscottl	u_int64_t p;
247175942Sscottl	u_int32_t outbound_tail = BUS_SPACE_RD4_MV2(outbound_tail);
248175942Sscottl	u_int32_t outbound_head = BUS_SPACE_RD4_MV2(outbound_head);
249175942Sscottl
250175942Sscottl	if (outbound_tail != outbound_head) {
251175942Sscottl		bus_space_read_region_4(hba->bar2t, hba->bar2h,
252175942Sscottl			offsetof(struct hpt_iopmu_mv,
253175942Sscottl				outbound_q[outbound_tail]),
254175942Sscottl			(u_int32_t *)&p, 2);
255175942Sscottl
256175942Sscottl		outbound_tail++;
257175942Sscottl
258175942Sscottl		if (outbound_tail == MVIOP_QUEUE_LEN)
259175942Sscottl			outbound_tail = 0;
260175942Sscottl
261175942Sscottl		BUS_SPACE_WRT4_MV2(outbound_tail, outbound_tail);
262175942Sscottl		return p;
263175942Sscottl	} else
264175942Sscottl		return 0;
265169412Sscottl}
266169412Sscottl
267175942Sscottlstatic void hptiop_mv_inbound_write(u_int64_t p, struct hpt_iop_hba *hba)
268169412Sscottl{
269175942Sscottl	u_int32_t inbound_head = BUS_SPACE_RD4_MV2(inbound_head);
270175942Sscottl	u_int32_t head = inbound_head + 1;
271175942Sscottl
272175942Sscottl	if (head == MVIOP_QUEUE_LEN)
273175942Sscottl		head = 0;
274175942Sscottl
275175942Sscottl	bus_space_write_region_4(hba->bar2t, hba->bar2h,
276175942Sscottl			offsetof(struct hpt_iopmu_mv, inbound_q[inbound_head]),
277175942Sscottl			(u_int32_t *)&p, 2);
278175942Sscottl	BUS_SPACE_WRT4_MV2(inbound_head, head);
279175942Sscottl	BUS_SPACE_WRT4_MV0(inbound_doorbell, MVIOP_MU_INBOUND_INT_POSTQUEUE);
280169412Sscottl}
281169412Sscottl
282175942Sscottlstatic void hptiop_post_msg_itl(struct hpt_iop_hba *hba, u_int32_t msg)
283169412Sscottl{
284175942Sscottl	BUS_SPACE_WRT4_ITL(inbound_msgaddr0, msg);
285175942Sscottl	BUS_SPACE_RD4_ITL(outbound_intstatus);
286169412Sscottl}
287169412Sscottl
288175942Sscottlstatic void hptiop_post_msg_mv(struct hpt_iop_hba *hba, u_int32_t msg)
289169412Sscottl{
290175942Sscottl
291175942Sscottl	BUS_SPACE_WRT4_MV2(inbound_msg, msg);
292175942Sscottl	BUS_SPACE_WRT4_MV0(inbound_doorbell, MVIOP_MU_INBOUND_INT_MSG);
293175942Sscottl
294175942Sscottl	BUS_SPACE_RD4_MV0(outbound_intmask);
295169412Sscottl}
296169412Sscottl
297175942Sscottlstatic int hptiop_wait_ready_itl(struct hpt_iop_hba * hba, u_int32_t millisec)
298169412Sscottl{
299169412Sscottl	u_int32_t req=0;
300169412Sscottl	int i;
301169412Sscottl
302169412Sscottl	for (i = 0; i < millisec; i++) {
303175942Sscottl		req = BUS_SPACE_RD4_ITL(inbound_queue);
304169412Sscottl		if (req != IOPMU_QUEUE_EMPTY)
305169412Sscottl			break;
306169412Sscottl		DELAY(1000);
307169412Sscottl	}
308169412Sscottl
309169412Sscottl	if (req!=IOPMU_QUEUE_EMPTY) {
310175942Sscottl		BUS_SPACE_WRT4_ITL(outbound_queue, req);
311175942Sscottl		BUS_SPACE_RD4_ITL(outbound_intstatus);
312169412Sscottl		return 0;
313169412Sscottl	}
314169412Sscottl
315169412Sscottl	return -1;
316169412Sscottl}
317169412Sscottl
318175942Sscottlstatic int hptiop_wait_ready_mv(struct hpt_iop_hba * hba, u_int32_t millisec)
319169412Sscottl{
320175942Sscottl	if (hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_NOP, millisec))
321175942Sscottl		return -1;
322175942Sscottl
323175942Sscottl	return 0;
324175942Sscottl}
325175942Sscottl
326175942Sscottlstatic void hptiop_request_callback_itl(struct hpt_iop_hba * hba,
327175942Sscottl							u_int32_t index)
328175942Sscottl{
329175942Sscottl	struct hpt_iop_srb *srb;
330175942Sscottl	struct hpt_iop_request_scsi_command *req=0;
331175942Sscottl	union ccb *ccb;
332175942Sscottl	u_int8_t *cdb;
333175942Sscottl	u_int32_t result, temp, dxfer;
334175942Sscottl	u_int64_t temp64;
335175942Sscottl
336175942Sscottl	if (index & IOPMU_QUEUE_MASK_HOST_BITS) { /*host req*/
337175942Sscottl		if (hba->firmware_version > 0x01020000 ||
338175942Sscottl			hba->interface_version > 0x01020000) {
339175942Sscottl			srb = hba->srb[index & ~(u_int32_t)
340175942Sscottl				(IOPMU_QUEUE_ADDR_HOST_BIT
341175942Sscottl				| IOPMU_QUEUE_REQUEST_RESULT_BIT)];
342175942Sscottl			req = (struct hpt_iop_request_scsi_command *)srb;
343175942Sscottl			if (index & IOPMU_QUEUE_REQUEST_RESULT_BIT)
344175942Sscottl				result = IOP_RESULT_SUCCESS;
345175942Sscottl			else
346175942Sscottl				result = req->header.result;
347175942Sscottl		} else {
348175942Sscottl			srb = hba->srb[index &
349175942Sscottl				~(u_int32_t)IOPMU_QUEUE_ADDR_HOST_BIT];
350175942Sscottl			req = (struct hpt_iop_request_scsi_command *)srb;
351175942Sscottl			result = req->header.result;
352175942Sscottl		}
353175942Sscottl		dxfer = req->dataxfer_length;
354175942Sscottl		goto srb_complete;
355175942Sscottl	}
356175942Sscottl
357175942Sscottl	/*iop req*/
358175942Sscottl	temp = bus_space_read_4(hba->bar0t, hba->bar0h, index +
359175942Sscottl		offsetof(struct hpt_iop_request_header, type));
360175942Sscottl	result = bus_space_read_4(hba->bar0t, hba->bar0h, index +
361175942Sscottl		offsetof(struct hpt_iop_request_header, result));
362175942Sscottl	switch(temp) {
363175942Sscottl	case IOP_REQUEST_TYPE_IOCTL_COMMAND:
364175942Sscottl	{
365175942Sscottl		temp64 = 0;
366175942Sscottl		bus_space_write_region_4(hba->bar0t, hba->bar0h, index +
367175942Sscottl			offsetof(struct hpt_iop_request_header, context),
368175942Sscottl			(u_int32_t *)&temp64, 2);
369175942Sscottl		wakeup((void *)((unsigned long)hba->u.itl.mu + index));
370175942Sscottl		break;
371175942Sscottl	}
372175942Sscottl
373175942Sscottl	case IOP_REQUEST_TYPE_SCSI_COMMAND:
374175942Sscottl		bus_space_read_region_4(hba->bar0t, hba->bar0h, index +
375175942Sscottl			offsetof(struct hpt_iop_request_header, context),
376175942Sscottl			(u_int32_t *)&temp64, 2);
377175942Sscottl		srb = (struct hpt_iop_srb *)(unsigned long)temp64;
378175942Sscottl		dxfer = bus_space_read_4(hba->bar0t, hba->bar0h,
379175942Sscottl				index + offsetof(struct hpt_iop_request_scsi_command,
380175942Sscottl				dataxfer_length));
381175942Sscottlsrb_complete:
382175942Sscottl		ccb = (union ccb *)srb->ccb;
383175942Sscottl		if (ccb->ccb_h.flags & CAM_CDB_POINTER)
384175942Sscottl			cdb = ccb->csio.cdb_io.cdb_ptr;
385175942Sscottl		else
386175942Sscottl			cdb = ccb->csio.cdb_io.cdb_bytes;
387175942Sscottl
388175942Sscottl		if (cdb[0] == SYNCHRONIZE_CACHE) { /* ??? */
389175942Sscottl			ccb->ccb_h.status = CAM_REQ_CMP;
390175942Sscottl			goto scsi_done;
391175942Sscottl		}
392175942Sscottl
393175942Sscottl		switch (result) {
394175942Sscottl		case IOP_RESULT_SUCCESS:
395175942Sscottl			switch (ccb->ccb_h.flags & CAM_DIR_MASK) {
396175942Sscottl			case CAM_DIR_IN:
397175942Sscottl				bus_dmamap_sync(hba->io_dmat,
398175942Sscottl					srb->dma_map, BUS_DMASYNC_POSTREAD);
399175942Sscottl				bus_dmamap_unload(hba->io_dmat, srb->dma_map);
400175942Sscottl				break;
401175942Sscottl			case CAM_DIR_OUT:
402175942Sscottl				bus_dmamap_sync(hba->io_dmat,
403175942Sscottl					srb->dma_map, BUS_DMASYNC_POSTWRITE);
404175942Sscottl				bus_dmamap_unload(hba->io_dmat, srb->dma_map);
405175942Sscottl				break;
406175942Sscottl			}
407175942Sscottl
408175942Sscottl			ccb->ccb_h.status = CAM_REQ_CMP;
409175942Sscottl			break;
410175942Sscottl
411175942Sscottl		case IOP_RESULT_BAD_TARGET:
412175942Sscottl			ccb->ccb_h.status = CAM_DEV_NOT_THERE;
413175942Sscottl			break;
414175942Sscottl		case IOP_RESULT_BUSY:
415175942Sscottl			ccb->ccb_h.status = CAM_BUSY;
416175942Sscottl			break;
417175942Sscottl		case IOP_RESULT_INVALID_REQUEST:
418175942Sscottl			ccb->ccb_h.status = CAM_REQ_INVALID;
419175942Sscottl			break;
420175942Sscottl		case IOP_RESULT_FAIL:
421175942Sscottl			ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
422175942Sscottl			break;
423175942Sscottl		case IOP_RESULT_RESET:
424175942Sscottl			ccb->ccb_h.status = CAM_BUSY;
425175942Sscottl			break;
426175942Sscottl		case IOP_RESULT_CHECK_CONDITION:
427175942Sscottl			if (srb->srb_flag & HPT_SRB_FLAG_HIGH_MEM_ACESS) {/*iop*/
428175942Sscottl				bus_space_read_region_1(hba->bar0t, hba->bar0h,
429175942Sscottl					index + offsetof(struct hpt_iop_request_scsi_command,
430175942Sscottl					sg_list), (u_int8_t *)&ccb->csio.sense_data,
431175942Sscottl					MIN(dxfer, sizeof(ccb->csio.sense_data)));
432175942Sscottl			} else {
433175942Sscottl				memcpy(&ccb->csio.sense_data, &req->sg_list,
434175942Sscottl					MIN(dxfer, sizeof(ccb->csio.sense_data)));
435175942Sscottl			}
436175942Sscottl			ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
437175942Sscottl			ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
438175942Sscottl			ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
439175942Sscottl			break;
440175942Sscottl		default:
441175942Sscottl			ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
442175942Sscottl			break;
443175942Sscottl		}
444175942Sscottlscsi_done:
445175942Sscottl		if (srb->srb_flag & HPT_SRB_FLAG_HIGH_MEM_ACESS)
446175942Sscottl			BUS_SPACE_WRT4_ITL(outbound_queue, index);
447175942Sscottl
448175942Sscottl		ccb->csio.resid = ccb->csio.dxfer_len - dxfer;
449175942Sscottl
450175942Sscottl		hptiop_free_srb(hba, srb);
451175942Sscottl		xpt_done(ccb);
452175942Sscottl		break;
453175942Sscottl	}
454175942Sscottl}
455175942Sscottl
456175942Sscottlstatic void hptiop_drain_outbound_queue_itl(struct hpt_iop_hba *hba)
457175942Sscottl{
458175942Sscottl	u_int32_t req, temp;
459175942Sscottl
460175942Sscottl	while ((req = BUS_SPACE_RD4_ITL(outbound_queue)) !=IOPMU_QUEUE_EMPTY) {
461175942Sscottl		if (req & IOPMU_QUEUE_MASK_HOST_BITS)
462175942Sscottl			hptiop_request_callback_itl(hba, req);
463175942Sscottl		else {
464175942Sscottl			struct hpt_iop_request_header *p;
465175942Sscottl
466175942Sscottl			p = (struct hpt_iop_request_header *)
467175942Sscottl				((char *)hba->u.itl.mu + req);
468175942Sscottl			temp = bus_space_read_4(hba->bar0t,
469175942Sscottl					hba->bar0h,req +
470175942Sscottl					offsetof(struct hpt_iop_request_header,
471175942Sscottl						flags));
472175942Sscottl			if (temp & IOP_REQUEST_FLAG_SYNC_REQUEST) {
473175942Sscottl				u_int64_t temp64;
474175942Sscottl				bus_space_read_region_4(hba->bar0t,
475175942Sscottl					hba->bar0h,req +
476175942Sscottl					offsetof(struct hpt_iop_request_header,
477175942Sscottl						context),
478175942Sscottl					(u_int32_t *)&temp64, 2);
479175942Sscottl				if (temp64) {
480175942Sscottl					hptiop_request_callback_itl(hba, req);
481175942Sscottl				} else {
482175942Sscottl					temp64 = 1;
483175942Sscottl					bus_space_write_region_4(hba->bar0t,
484175942Sscottl						hba->bar0h,req +
485175942Sscottl						offsetof(struct hpt_iop_request_header,
486175942Sscottl							context),
487175942Sscottl						(u_int32_t *)&temp64, 2);
488175942Sscottl				}
489175942Sscottl			} else
490175942Sscottl				hptiop_request_callback_itl(hba, req);
491175942Sscottl		}
492175942Sscottl	}
493175942Sscottl}
494175942Sscottl
495175942Sscottlstatic int hptiop_intr_itl(struct hpt_iop_hba * hba)
496175942Sscottl{
497169412Sscottl	u_int32_t status;
498169412Sscottl	int ret = 0;
499169412Sscottl
500175942Sscottl	status = BUS_SPACE_RD4_ITL(outbound_intstatus);
501169412Sscottl
502169412Sscottl	if (status & IOPMU_OUTBOUND_INT_MSG0) {
503175942Sscottl		u_int32_t msg = BUS_SPACE_RD4_ITL(outbound_msgaddr0);
504175942Sscottl		KdPrint(("hptiop: received outbound msg %x\n", msg));
505175942Sscottl		BUS_SPACE_WRT4_ITL(outbound_intstatus, IOPMU_OUTBOUND_INT_MSG0);
506175942Sscottl		hptiop_os_message_callback(hba, msg);
507169412Sscottl		ret = 1;
508169412Sscottl	}
509169412Sscottl
510169412Sscottl	if (status & IOPMU_OUTBOUND_INT_POSTQUEUE) {
511175942Sscottl		hptiop_drain_outbound_queue_itl(hba);
512175942Sscottl		ret = 1;
513175942Sscottl	}
514175942Sscottl
515175942Sscottl	return ret;
516175942Sscottl}
517175942Sscottl
518175942Sscottlstatic void hptiop_request_callback_mv(struct hpt_iop_hba * hba,
519175942Sscottl							u_int64_t _tag)
520175942Sscottl{
521175942Sscottl	u_int32_t context = (u_int32_t)_tag;
522175942Sscottl
523175942Sscottl	if (context & MVIOP_CMD_TYPE_SCSI) {
524175942Sscottl		struct hpt_iop_srb *srb;
525175942Sscottl		struct hpt_iop_request_scsi_command *req;
526175942Sscottl		union ccb *ccb;
527175942Sscottl		u_int8_t *cdb;
528175942Sscottl
529175942Sscottl		srb = hba->srb[context >> MVIOP_REQUEST_NUMBER_START_BIT];
530175942Sscottl		req = (struct hpt_iop_request_scsi_command *)srb;
531175942Sscottl		ccb = (union ccb *)srb->ccb;
532175942Sscottl		if (ccb->ccb_h.flags & CAM_CDB_POINTER)
533175942Sscottl			cdb = ccb->csio.cdb_io.cdb_ptr;
534175942Sscottl		else
535175942Sscottl			cdb = ccb->csio.cdb_io.cdb_bytes;
536175942Sscottl
537175942Sscottl		if (cdb[0] == SYNCHRONIZE_CACHE) { /* ??? */
538175942Sscottl			ccb->ccb_h.status = CAM_REQ_CMP;
539175942Sscottl			goto scsi_done;
540175942Sscottl		}
541175942Sscottl		if (context & MVIOP_MU_QUEUE_REQUEST_RESULT_BIT)
542175942Sscottl			req->header.result = IOP_RESULT_SUCCESS;
543175942Sscottl
544175942Sscottl		switch (req->header.result) {
545175942Sscottl		case IOP_RESULT_SUCCESS:
546175942Sscottl			switch (ccb->ccb_h.flags & CAM_DIR_MASK) {
547175942Sscottl			case CAM_DIR_IN:
548175942Sscottl				bus_dmamap_sync(hba->io_dmat,
549175942Sscottl					srb->dma_map, BUS_DMASYNC_POSTREAD);
550175942Sscottl				bus_dmamap_unload(hba->io_dmat, srb->dma_map);
551175942Sscottl				break;
552175942Sscottl			case CAM_DIR_OUT:
553175942Sscottl				bus_dmamap_sync(hba->io_dmat,
554175942Sscottl					srb->dma_map, BUS_DMASYNC_POSTWRITE);
555175942Sscottl				bus_dmamap_unload(hba->io_dmat, srb->dma_map);
556175942Sscottl				break;
557169412Sscottl			}
558175942Sscottl			ccb->ccb_h.status = CAM_REQ_CMP;
559175942Sscottl			break;
560175942Sscottl		case IOP_RESULT_BAD_TARGET:
561175942Sscottl			ccb->ccb_h.status = CAM_DEV_NOT_THERE;
562175942Sscottl			break;
563175942Sscottl		case IOP_RESULT_BUSY:
564175942Sscottl			ccb->ccb_h.status = CAM_BUSY;
565175942Sscottl			break;
566175942Sscottl		case IOP_RESULT_INVALID_REQUEST:
567175942Sscottl			ccb->ccb_h.status = CAM_REQ_INVALID;
568175942Sscottl			break;
569175942Sscottl		case IOP_RESULT_FAIL:
570175942Sscottl			ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
571175942Sscottl			break;
572175942Sscottl		case IOP_RESULT_RESET:
573175942Sscottl			ccb->ccb_h.status = CAM_BUSY;
574175942Sscottl			break;
575175942Sscottl		case IOP_RESULT_CHECK_CONDITION:
576175942Sscottl			memcpy(&ccb->csio.sense_data, &req->sg_list,
577175942Sscottl				MIN(req->dataxfer_length, sizeof(ccb->csio.sense_data)));
578175942Sscottl			ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
579175942Sscottl			ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
580175942Sscottl			ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
581175942Sscottl			break;
582175942Sscottl		default:
583175942Sscottl			ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
584175942Sscottl			break;
585169412Sscottl		}
586175942Sscottlscsi_done:
587175942Sscottl		ccb->csio.resid = ccb->csio.dxfer_len - req->dataxfer_length;
588175942Sscottl
589175942Sscottl		hptiop_free_srb(hba, srb);
590175942Sscottl		xpt_done(ccb);
591175942Sscottl	} else if (context & MVIOP_CMD_TYPE_IOCTL) {
592175942Sscottl		struct hpt_iop_request_ioctl_command *req = hba->ctlcfg_ptr;
593175942Sscottl		if (context & MVIOP_MU_QUEUE_REQUEST_RESULT_BIT)
594175942Sscottl			hba->config_done = 1;
595175942Sscottl		else
596175942Sscottl			hba->config_done = -1;
597175942Sscottl		wakeup(req);
598175942Sscottl	} else if (context &
599175942Sscottl			(MVIOP_CMD_TYPE_SET_CONFIG |
600175942Sscottl				MVIOP_CMD_TYPE_GET_CONFIG))
601175942Sscottl		hba->config_done = 1;
602175942Sscottl	else {
603175942Sscottl		device_printf(hba->pcidev, "wrong callback type\n");
604175942Sscottl	}
605175942Sscottl}
606175942Sscottl
607175942Sscottlstatic void hptiop_drain_outbound_queue_mv(struct hpt_iop_hba * hba)
608175942Sscottl{
609175942Sscottl	u_int64_t req;
610175942Sscottl
611175942Sscottl	while ((req = hptiop_mv_outbound_read(hba))) {
612175942Sscottl		if (req & MVIOP_MU_QUEUE_ADDR_HOST_BIT) {
613175942Sscottl			if (req & MVIOP_MU_QUEUE_REQUEST_RETURN_CONTEXT) {
614175942Sscottl				hptiop_request_callback_mv(hba, req);
615175942Sscottl			}
616175942Sscottl	    	}
617175942Sscottl	}
618175942Sscottl}
619175942Sscottl
620175942Sscottlstatic int hptiop_intr_mv(struct hpt_iop_hba * hba)
621175942Sscottl{
622175942Sscottl	u_int32_t status;
623175942Sscottl	int ret = 0;
624175942Sscottl
625175942Sscottl	status = BUS_SPACE_RD4_MV0(outbound_doorbell);
626175942Sscottl
627175942Sscottl	if (status)
628175942Sscottl		BUS_SPACE_WRT4_MV0(outbound_doorbell, ~status);
629175942Sscottl
630175942Sscottl	if (status & MVIOP_MU_OUTBOUND_INT_MSG) {
631175942Sscottl		u_int32_t msg = BUS_SPACE_RD4_MV2(outbound_msg);
632175942Sscottl		KdPrint(("hptiop: received outbound msg %x\n", msg));
633175942Sscottl		hptiop_os_message_callback(hba, msg);
634169412Sscottl		ret = 1;
635169412Sscottl	}
636175942Sscottl
637175942Sscottl	if (status & MVIOP_MU_OUTBOUND_INT_POSTQUEUE) {
638175942Sscottl		hptiop_drain_outbound_queue_mv(hba);
639175942Sscottl		ret = 1;
640175942Sscottl	}
641175942Sscottl
642169412Sscottl	return ret;
643169412Sscottl}
644169412Sscottl
645175942Sscottlstatic int hptiop_send_sync_request_itl(struct hpt_iop_hba * hba,
646175942Sscottl					u_int32_t req32, u_int32_t millisec)
647169412Sscottl{
648169412Sscottl	u_int32_t i;
649175942Sscottl	u_int64_t temp64;
650169412Sscottl
651175942Sscottl	BUS_SPACE_WRT4_ITL(inbound_queue, req32);
652175942Sscottl	BUS_SPACE_RD4_ITL(outbound_intstatus);
653169412Sscottl
654169412Sscottl	for (i = 0; i < millisec; i++) {
655175942Sscottl		hptiop_intr_itl(hba);
656175942Sscottl		bus_space_read_region_4(hba->bar0t, hba->bar0h, req32 +
657175942Sscottl			offsetof(struct hpt_iop_request_header, context),
658175942Sscottl			(u_int32_t *)&temp64, 2);
659175942Sscottl		if (temp64)
660169412Sscottl			return 0;
661169412Sscottl		DELAY(1000);
662169412Sscottl	}
663169412Sscottl
664169412Sscottl	return -1;
665169412Sscottl}
666169412Sscottl
667175942Sscottlstatic int hptiop_send_sync_request_mv(struct hpt_iop_hba *hba,
668175942Sscottl					void *req, u_int32_t millisec)
669169412Sscottl{
670169412Sscottl	u_int32_t i;
671175942Sscottl	u_int64_t phy_addr;
672175942Sscottl	hba->config_done = 0;
673169412Sscottl
674175942Sscottl	phy_addr = hba->ctlcfgcmd_phy |
675175942Sscottl			(u_int64_t)MVIOP_MU_QUEUE_ADDR_HOST_BIT;
676175942Sscottl	((struct hpt_iop_request_get_config *)req)->header.flags |=
677175942Sscottl		IOP_REQUEST_FLAG_SYNC_REQUEST |
678175942Sscottl		IOP_REQUEST_FLAG_OUTPUT_CONTEXT;
679175942Sscottl	hptiop_mv_inbound_write(phy_addr, hba);
680175942Sscottl	BUS_SPACE_RD4_MV0(outbound_intmask);
681169412Sscottl
682175942Sscottl	for (i = 0; i < millisec; i++) {
683175942Sscottl		hptiop_intr_mv(hba);
684175942Sscottl		if (hba->config_done)
685175942Sscottl			return 0;
686175942Sscottl		DELAY(1000);
687175942Sscottl	}
688175942Sscottl	return -1;
689175942Sscottl}
690169412Sscottl
691175942Sscottlstatic int hptiop_send_sync_msg(struct hpt_iop_hba *hba,
692175942Sscottl					u_int32_t msg, u_int32_t millisec)
693175942Sscottl{
694175942Sscottl	u_int32_t i;
695169412Sscottl
696175942Sscottl	hba->msg_done = 0;
697175942Sscottl	hba->ops->post_msg(hba, msg);
698175942Sscottl
699175942Sscottl	for (i=0; i<millisec; i++) {
700175942Sscottl		hba->ops->iop_intr(hba);
701175942Sscottl		if (hba->msg_done)
702169412Sscottl			break;
703169412Sscottl		DELAY(1000);
704169412Sscottl	}
705169412Sscottl
706175942Sscottl	return hba->msg_done? 0 : -1;
707169412Sscottl}
708169412Sscottl
709175942Sscottlstatic int hptiop_get_config_itl(struct hpt_iop_hba * hba,
710175942Sscottl				struct hpt_iop_request_get_config * config)
711169412Sscottl{
712175942Sscottl	u_int32_t req32;
713169412Sscottl
714175942Sscottl	config->header.size = sizeof(struct hpt_iop_request_get_config);
715175942Sscottl	config->header.type = IOP_REQUEST_TYPE_GET_CONFIG;
716175942Sscottl	config->header.flags = IOP_REQUEST_FLAG_SYNC_REQUEST;
717175942Sscottl	config->header.result = IOP_RESULT_PENDING;
718175942Sscottl	config->header.context = 0;
719175942Sscottl
720175942Sscottl	req32 = BUS_SPACE_RD4_ITL(inbound_queue);
721175942Sscottl	if (req32 == IOPMU_QUEUE_EMPTY)
722169412Sscottl		return -1;
723169412Sscottl
724175942Sscottl	bus_space_write_region_4(hba->bar0t, hba->bar0h,
725175942Sscottl			req32, (u_int32_t *)config,
726175942Sscottl			sizeof(struct hpt_iop_request_header) >> 2);
727175942Sscottl
728175942Sscottl	if (hptiop_send_sync_request_itl(hba, req32, 20000)) {
729175942Sscottl		KdPrint(("hptiop: get config send cmd failed"));
730175942Sscottl		return -1;
731175942Sscottl	}
732175942Sscottl
733175942Sscottl	bus_space_read_region_4(hba->bar0t, hba->bar0h,
734175942Sscottl			req32, (u_int32_t *)config,
735175942Sscottl			sizeof(struct hpt_iop_request_get_config) >> 2);
736175942Sscottl
737175942Sscottl	BUS_SPACE_WRT4_ITL(outbound_queue, req32);
738175942Sscottl
739175942Sscottl	return 0;
740175942Sscottl}
741175942Sscottl
742175942Sscottlstatic int hptiop_get_config_mv(struct hpt_iop_hba * hba,
743175942Sscottl				struct hpt_iop_request_get_config * config)
744175942Sscottl{
745175942Sscottl	struct hpt_iop_request_get_config *req;
746175942Sscottl
747175942Sscottl	if (!(req = hba->ctlcfg_ptr))
748175942Sscottl		return -1;
749175942Sscottl
750169412Sscottl	req->header.flags = 0;
751169412Sscottl	req->header.type = IOP_REQUEST_TYPE_GET_CONFIG;
752169412Sscottl	req->header.size = sizeof(struct hpt_iop_request_get_config);
753169412Sscottl	req->header.result = IOP_RESULT_PENDING;
754175942Sscottl	req->header.context = MVIOP_CMD_TYPE_GET_CONFIG;
755169412Sscottl
756175942Sscottl	if (hptiop_send_sync_request_mv(hba, req, 20000)) {
757175942Sscottl		KdPrint(("hptiop: get config send cmd failed"));
758169412Sscottl		return -1;
759169412Sscottl	}
760169412Sscottl
761169412Sscottl	*config = *req;
762169412Sscottl	return 0;
763169412Sscottl}
764169412Sscottl
765175942Sscottlstatic int hptiop_set_config_itl(struct hpt_iop_hba *hba,
766175942Sscottl				struct hpt_iop_request_set_config *config)
767169412Sscottl{
768169412Sscottl	u_int32_t req32;
769169412Sscottl
770175942Sscottl	req32 = BUS_SPACE_RD4_ITL(inbound_queue);
771175942Sscottl
772169412Sscottl	if (req32 == IOPMU_QUEUE_EMPTY)
773169412Sscottl		return -1;
774169412Sscottl
775175942Sscottl	config->header.size = sizeof(struct hpt_iop_request_set_config);
776175942Sscottl	config->header.type = IOP_REQUEST_TYPE_SET_CONFIG;
777175942Sscottl	config->header.flags = IOP_REQUEST_FLAG_SYNC_REQUEST;
778175942Sscottl	config->header.result = IOP_RESULT_PENDING;
779175942Sscottl	config->header.context = 0;
780175942Sscottl
781175942Sscottl	bus_space_write_region_4(hba->bar0t, hba->bar0h, req32,
782175942Sscottl		(u_int32_t *)config,
783175942Sscottl		sizeof(struct hpt_iop_request_set_config) >> 2);
784175942Sscottl
785175942Sscottl	if (hptiop_send_sync_request_itl(hba, req32, 20000)) {
786175942Sscottl		KdPrint(("hptiop: set config send cmd failed"));
787175942Sscottl		return -1;
788175942Sscottl	}
789175942Sscottl
790175942Sscottl	BUS_SPACE_WRT4_ITL(outbound_queue, req32);
791175942Sscottl
792175942Sscottl	return 0;
793175942Sscottl}
794175942Sscottl
795175942Sscottlstatic int hptiop_set_config_mv(struct hpt_iop_hba *hba,
796175942Sscottl				struct hpt_iop_request_set_config *config)
797175942Sscottl{
798175942Sscottl	struct hpt_iop_request_set_config *req;
799175942Sscottl
800175942Sscottl	if (!(req = hba->ctlcfg_ptr))
801175942Sscottl		return -1;
802175942Sscottl
803169412Sscottl	memcpy((u_int8_t *)req + sizeof(struct hpt_iop_request_header),
804169412Sscottl		(u_int8_t *)config + sizeof(struct hpt_iop_request_header),
805175942Sscottl		sizeof(struct hpt_iop_request_set_config) -
806175942Sscottl			sizeof(struct hpt_iop_request_header));
807175942Sscottl
808169412Sscottl	req->header.flags = 0;
809169412Sscottl	req->header.type = IOP_REQUEST_TYPE_SET_CONFIG;
810169412Sscottl	req->header.size = sizeof(struct hpt_iop_request_set_config);
811169412Sscottl	req->header.result = IOP_RESULT_PENDING;
812175942Sscottl	req->header.context = MVIOP_CMD_TYPE_SET_CONFIG;
813169412Sscottl
814175942Sscottl	if (hptiop_send_sync_request_mv(hba, req, 20000)) {
815175942Sscottl		KdPrint(("hptiop: set config send cmd failed"));
816169412Sscottl		return -1;
817169412Sscottl	}
818169412Sscottl
819169412Sscottl	return 0;
820169412Sscottl}
821169412Sscottl
822175942Sscottlstatic int hptiop_post_ioctl_command_itl(struct hpt_iop_hba *hba,
823175942Sscottl				u_int32_t req32,
824175942Sscottl				struct hpt_iop_ioctl_param *pParams)
825169412Sscottl{
826175942Sscottl	u_int64_t temp64;
827175942Sscottl	struct hpt_iop_request_ioctl_command req;
828169412Sscottl
829175942Sscottl	if ((((pParams->nInBufferSize + 3) & ~3) + pParams->nOutBufferSize) >
830175942Sscottl			(hba->max_request_size -
831175942Sscottl			offsetof(struct hpt_iop_request_ioctl_command, buf))) {
832175942Sscottl		device_printf(hba->pcidev, "request size beyond max value");
833175942Sscottl		return -1;
834175942Sscottl	}
835175942Sscottl
836175942Sscottl	req.header.size = offsetof(struct hpt_iop_request_ioctl_command, buf)
837175942Sscottl		+ pParams->nInBufferSize;
838175942Sscottl	req.header.type = IOP_REQUEST_TYPE_IOCTL_COMMAND;
839175942Sscottl	req.header.flags = IOP_REQUEST_FLAG_SYNC_REQUEST;
840175942Sscottl	req.header.result = IOP_RESULT_PENDING;
841175942Sscottl	req.header.context = req32 + (u_int64_t)(unsigned long)hba->u.itl.mu;
842175942Sscottl	req.ioctl_code = HPT_CTL_CODE_BSD_TO_IOP(pParams->dwIoControlCode);
843175942Sscottl	req.inbuf_size = pParams->nInBufferSize;
844175942Sscottl	req.outbuf_size = pParams->nOutBufferSize;
845175942Sscottl	req.bytes_returned = 0;
846175942Sscottl
847175942Sscottl	bus_space_write_region_4(hba->bar0t, hba->bar0h, req32, (u_int32_t *)&req,
848175942Sscottl		offsetof(struct hpt_iop_request_ioctl_command, buf)>>2);
849175942Sscottl
850175942Sscottl	hptiop_lock_adapter(hba);
851175942Sscottl
852175942Sscottl	BUS_SPACE_WRT4_ITL(inbound_queue, req32);
853175942Sscottl	BUS_SPACE_RD4_ITL(outbound_intstatus);
854175942Sscottl
855175942Sscottl	bus_space_read_region_4(hba->bar0t, hba->bar0h, req32 +
856175942Sscottl		offsetof(struct hpt_iop_request_ioctl_command, header.context),
857175942Sscottl		(u_int32_t *)&temp64, 2);
858175942Sscottl	while (temp64) {
859175942Sscottl		if (hptiop_sleep(hba, (void *)((unsigned long)hba->u.itl.mu + req32),
860175942Sscottl				PPAUSE, "hptctl", HPT_OSM_TIMEOUT)==0)
861175942Sscottl			break;
862175942Sscottl		hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_RESET, 60000);
863175942Sscottl		bus_space_read_region_4(hba->bar0t, hba->bar0h,req32 +
864175942Sscottl			offsetof(struct hpt_iop_request_ioctl_command,
865175942Sscottl				header.context),
866175942Sscottl			(u_int32_t *)&temp64, 2);
867175942Sscottl	}
868175942Sscottl
869175942Sscottl	hptiop_unlock_adapter(hba);
870175942Sscottl	return 0;
871175942Sscottl}
872175942Sscottl
873175942Sscottlstatic int hptiop_bus_space_copyin(struct hpt_iop_hba *hba, u_int32_t bus, void *user, int size)
874175942Sscottl{
875175942Sscottl	unsigned char byte;
876175942Sscottl	int i;
877175942Sscottl
878175942Sscottl	for (i=0; i<size; i++) {
879175942Sscottl		if (copyin((u_int8_t *)user + i, &byte, 1))
880175942Sscottl			return -1;
881175942Sscottl		bus_space_write_1(hba->bar0t, hba->bar0h, bus + i, byte);
882175942Sscottl	}
883175942Sscottl
884175942Sscottl	return 0;
885175942Sscottl}
886175942Sscottl
887175942Sscottlstatic int hptiop_bus_space_copyout(struct hpt_iop_hba *hba, u_int32_t bus, void *user, int size)
888175942Sscottl{
889175942Sscottl	unsigned char byte;
890175942Sscottl	int i;
891175942Sscottl
892175942Sscottl	for (i=0; i<size; i++) {
893175942Sscottl		byte = bus_space_read_1(hba->bar0t, hba->bar0h, bus + i);
894175942Sscottl		if (copyout(&byte, (u_int8_t *)user + i, 1))
895175942Sscottl			return -1;
896175942Sscottl	}
897175942Sscottl
898175942Sscottl	return 0;
899175942Sscottl}
900175942Sscottl
901175942Sscottlstatic int hptiop_do_ioctl_itl(struct hpt_iop_hba *hba,
902175942Sscottl				struct hpt_iop_ioctl_param * pParams)
903175942Sscottl{
904175942Sscottl	u_int32_t req32;
905175942Sscottl	u_int32_t result;
906175942Sscottl
907169412Sscottl	if ((pParams->Magic != HPT_IOCTL_MAGIC) &&
908169412Sscottl		(pParams->Magic != HPT_IOCTL_MAGIC32))
909169412Sscottl		return EFAULT;
910175942Sscottl
911175942Sscottl	req32 = BUS_SPACE_RD4_ITL(inbound_queue);
912175942Sscottl	if (req32 == IOPMU_QUEUE_EMPTY)
913169412Sscottl		return EFAULT;
914169412Sscottl
915169412Sscottl	if (pParams->nInBufferSize)
916175942Sscottl		if (hptiop_bus_space_copyin(hba, req32 +
917175942Sscottl			offsetof(struct hpt_iop_request_ioctl_command, buf),
918175942Sscottl			(void *)pParams->lpInBuffer, pParams->nInBufferSize))
919169412Sscottl			goto invalid;
920169412Sscottl
921175942Sscottl	if (hptiop_post_ioctl_command_itl(hba, req32, pParams))
922169412Sscottl		goto invalid;
923169412Sscottl
924175942Sscottl	result = bus_space_read_4(hba->bar0t, hba->bar0h, req32 +
925175942Sscottl			offsetof(struct hpt_iop_request_ioctl_command,
926175942Sscottl				header.result));
927175942Sscottl
928175942Sscottl	if (result == IOP_RESULT_SUCCESS) {
929169412Sscottl		if (pParams->nOutBufferSize)
930175942Sscottl			if (hptiop_bus_space_copyout(hba, req32 +
931175942Sscottl				offsetof(struct hpt_iop_request_ioctl_command, buf) +
932169412Sscottl					((pParams->nInBufferSize + 3) & ~3),
933175942Sscottl				(void *)pParams->lpOutBuffer, pParams->nOutBufferSize))
934169412Sscottl				goto invalid;
935169412Sscottl
936175942Sscottl		if (pParams->lpBytesReturned) {
937175942Sscottl			if (hptiop_bus_space_copyout(hba, req32 +
938175942Sscottl				offsetof(struct hpt_iop_request_ioctl_command, bytes_returned),
939175942Sscottl				(void *)pParams->lpBytesReturned, sizeof(unsigned  long)))
940169412Sscottl				goto invalid;
941175942Sscottl		}
942175942Sscottl
943175942Sscottl		BUS_SPACE_WRT4_ITL(outbound_queue, req32);
944175942Sscottl
945169412Sscottl		return 0;
946169412Sscottl	} else{
947169412Sscottlinvalid:
948175942Sscottl		BUS_SPACE_WRT4_ITL(outbound_queue, req32);
949175942Sscottl
950169412Sscottl		return EFAULT;
951169412Sscottl	}
952169412Sscottl}
953169412Sscottl
954175942Sscottlstatic int hptiop_post_ioctl_command_mv(struct hpt_iop_hba *hba,
955175942Sscottl				struct hpt_iop_request_ioctl_command *req,
956175942Sscottl				struct hpt_iop_ioctl_param *pParams)
957169412Sscottl{
958175942Sscottl	u_int64_t req_phy;
959175942Sscottl	int size = 0;
960175942Sscottl
961175942Sscottl	if ((((pParams->nInBufferSize + 3) & ~3) + pParams->nOutBufferSize) >
962175942Sscottl			(hba->max_request_size -
963175942Sscottl			offsetof(struct hpt_iop_request_ioctl_command, buf))) {
964175942Sscottl		device_printf(hba->pcidev, "request size beyond max value");
965169412Sscottl		return -1;
966169412Sscottl	}
967169412Sscottl
968169412Sscottl	req->ioctl_code = HPT_CTL_CODE_BSD_TO_IOP(pParams->dwIoControlCode);
969169412Sscottl	req->inbuf_size = pParams->nInBufferSize;
970169412Sscottl	req->outbuf_size = pParams->nOutBufferSize;
971175942Sscottl	req->header.size = offsetof(struct hpt_iop_request_ioctl_command, buf)
972175942Sscottl					+ pParams->nInBufferSize;
973175942Sscottl	req->header.context = (u_int64_t)MVIOP_CMD_TYPE_IOCTL;
974169412Sscottl	req->header.type = IOP_REQUEST_TYPE_IOCTL_COMMAND;
975169412Sscottl	req->header.result = IOP_RESULT_PENDING;
976175942Sscottl	req->header.flags = IOP_REQUEST_FLAG_OUTPUT_CONTEXT;
977175942Sscottl	size = req->header.size >> 8;
978175942Sscottl	size = size > 3 ? 3 : size;
979175942Sscottl	req_phy = hba->ctlcfgcmd_phy | MVIOP_MU_QUEUE_ADDR_HOST_BIT | size;
980175942Sscottl	hptiop_mv_inbound_write(req_phy, hba);
981169412Sscottl
982175942Sscottl	BUS_SPACE_RD4_MV0(outbound_intmask);
983169412Sscottl
984175942Sscottl	while (hba->config_done == 0) {
985175942Sscottl		if (hptiop_sleep(hba, req, PPAUSE,
986175942Sscottl			"hptctl", HPT_OSM_TIMEOUT)==0)
987175942Sscottl			continue;
988175942Sscottl		hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_RESET, 60000);
989169412Sscottl	}
990169412Sscottl	return 0;
991169412Sscottl}
992169412Sscottl
993175942Sscottlstatic int hptiop_do_ioctl_mv(struct hpt_iop_hba *hba,
994175942Sscottl				struct hpt_iop_ioctl_param *pParams)
995175942Sscottl{
996175942Sscottl	struct hpt_iop_request_ioctl_command *req;
997175942Sscottl
998175942Sscottl	if ((pParams->Magic != HPT_IOCTL_MAGIC) &&
999175942Sscottl		(pParams->Magic != HPT_IOCTL_MAGIC32))
1000175942Sscottl		return EFAULT;
1001175942Sscottl
1002175942Sscottl	req = (struct hpt_iop_request_ioctl_command *)(hba->ctlcfg_ptr);
1003175942Sscottl	hba->config_done = 0;
1004175942Sscottl	hptiop_lock_adapter(hba);
1005175942Sscottl	if (pParams->nInBufferSize)
1006175942Sscottl		if (copyin((void *)pParams->lpInBuffer,
1007175942Sscottl				req->buf, pParams->nInBufferSize))
1008175942Sscottl			goto invalid;
1009175942Sscottl	if (hptiop_post_ioctl_command_mv(hba, req, pParams))
1010175942Sscottl		goto invalid;
1011175942Sscottl
1012175942Sscottl	if (hba->config_done == 1) {
1013175942Sscottl		if (pParams->nOutBufferSize)
1014175942Sscottl			if (copyout(req->buf +
1015175942Sscottl				((pParams->nInBufferSize + 3) & ~3),
1016175942Sscottl				(void *)pParams->lpOutBuffer,
1017175942Sscottl				pParams->nOutBufferSize))
1018175942Sscottl				goto invalid;
1019175942Sscottl
1020175942Sscottl		if (pParams->lpBytesReturned)
1021175942Sscottl			if (copyout(&req->bytes_returned,
1022175942Sscottl				(void*)pParams->lpBytesReturned,
1023175942Sscottl				sizeof(u_int32_t)))
1024175942Sscottl				goto invalid;
1025175942Sscottl		hptiop_unlock_adapter(hba);
1026175942Sscottl		return 0;
1027175942Sscottl	} else{
1028175942Sscottlinvalid:
1029175942Sscottl		hptiop_unlock_adapter(hba);
1030175942Sscottl		return EFAULT;
1031175942Sscottl	}
1032175942Sscottl}
1033175942Sscottl
1034169412Sscottlstatic int  hptiop_rescan_bus(struct hpt_iop_hba * hba)
1035169412Sscottl{
1036169412Sscottl	union ccb           *ccb;
1037203108Smav
1038203108Smav	if ((ccb = xpt_alloc_ccb()) == NULL)
1039203108Smav		return(ENOMEM);
1040203108Smav	if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, cam_sim_path(hba->sim),
1041203108Smav		CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
1042203108Smav		xpt_free_ccb(ccb);
1043169412Sscottl		return(EIO);
1044203108Smav	}
1045203108Smav	xpt_rescan(ccb);
1046169412Sscottl	return(0);
1047169412Sscottl}
1048169412Sscottl
1049169412Sscottlstatic  bus_dmamap_callback_t   hptiop_map_srb;
1050169412Sscottlstatic  bus_dmamap_callback_t   hptiop_post_scsi_command;
1051175942Sscottlstatic  bus_dmamap_callback_t   hptiop_mv_map_ctlcfg;
1052169412Sscottl
1053175942Sscottlstatic int hptiop_alloc_pci_res_itl(struct hpt_iop_hba *hba)
1054175942Sscottl{
1055175942Sscottl	hba->bar0_rid = 0x10;
1056175942Sscottl	hba->bar0_res = bus_alloc_resource_any(hba->pcidev,
1057175942Sscottl			SYS_RES_MEMORY, &hba->bar0_rid, RF_ACTIVE);
1058175942Sscottl
1059175942Sscottl	if (hba->bar0_res == NULL) {
1060175942Sscottl		device_printf(hba->pcidev,
1061175942Sscottl			"failed to get iop base adrress.\n");
1062175942Sscottl		return -1;
1063175942Sscottl	}
1064175942Sscottl	hba->bar0t = rman_get_bustag(hba->bar0_res);
1065175942Sscottl	hba->bar0h = rman_get_bushandle(hba->bar0_res);
1066175942Sscottl	hba->u.itl.mu = (struct hpt_iopmu_itl *)
1067175942Sscottl				rman_get_virtual(hba->bar0_res);
1068175942Sscottl
1069175942Sscottl	if (!hba->u.itl.mu) {
1070175942Sscottl		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1071175942Sscottl					hba->bar0_rid, hba->bar0_res);
1072175942Sscottl		device_printf(hba->pcidev, "alloc mem res failed\n");
1073175942Sscottl		return -1;
1074175942Sscottl	}
1075175942Sscottl
1076175942Sscottl	return 0;
1077175942Sscottl}
1078175942Sscottl
1079175942Sscottlstatic int hptiop_alloc_pci_res_mv(struct hpt_iop_hba *hba)
1080175942Sscottl{
1081175942Sscottl	hba->bar0_rid = 0x10;
1082175942Sscottl	hba->bar0_res = bus_alloc_resource_any(hba->pcidev,
1083175942Sscottl			SYS_RES_MEMORY, &hba->bar0_rid, RF_ACTIVE);
1084175942Sscottl
1085175942Sscottl	if (hba->bar0_res == NULL) {
1086175942Sscottl		device_printf(hba->pcidev, "failed to get iop bar0.\n");
1087175942Sscottl		return -1;
1088175942Sscottl	}
1089175942Sscottl	hba->bar0t = rman_get_bustag(hba->bar0_res);
1090175942Sscottl	hba->bar0h = rman_get_bushandle(hba->bar0_res);
1091175942Sscottl	hba->u.mv.regs = (struct hpt_iopmv_regs *)
1092175942Sscottl				rman_get_virtual(hba->bar0_res);
1093175942Sscottl
1094175942Sscottl	if (!hba->u.mv.regs) {
1095175942Sscottl		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1096175942Sscottl					hba->bar0_rid, hba->bar0_res);
1097175942Sscottl		device_printf(hba->pcidev, "alloc bar0 mem res failed\n");
1098175942Sscottl		return -1;
1099175942Sscottl	}
1100175942Sscottl
1101175942Sscottl	hba->bar2_rid = 0x18;
1102175942Sscottl	hba->bar2_res = bus_alloc_resource_any(hba->pcidev,
1103175942Sscottl			SYS_RES_MEMORY, &hba->bar2_rid, RF_ACTIVE);
1104175942Sscottl
1105175942Sscottl	if (hba->bar2_res == NULL) {
1106175942Sscottl		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1107175942Sscottl					hba->bar0_rid, hba->bar0_res);
1108175942Sscottl		device_printf(hba->pcidev, "failed to get iop bar2.\n");
1109175942Sscottl		return -1;
1110175942Sscottl	}
1111175942Sscottl
1112175942Sscottl	hba->bar2t = rman_get_bustag(hba->bar2_res);
1113175942Sscottl	hba->bar2h = rman_get_bushandle(hba->bar2_res);
1114175942Sscottl	hba->u.mv.mu = (struct hpt_iopmu_mv *)rman_get_virtual(hba->bar2_res);
1115175942Sscottl
1116175942Sscottl	if (!hba->u.mv.mu) {
1117175942Sscottl		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1118175942Sscottl					hba->bar0_rid, hba->bar0_res);
1119175942Sscottl		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1120175942Sscottl					hba->bar2_rid, hba->bar2_res);
1121175942Sscottl		device_printf(hba->pcidev, "alloc mem bar2 res failed\n");
1122175942Sscottl		return -1;
1123175942Sscottl	}
1124175942Sscottl
1125175942Sscottl	return 0;
1126175942Sscottl}
1127175942Sscottl
1128175942Sscottlstatic void hptiop_release_pci_res_itl(struct hpt_iop_hba *hba)
1129175942Sscottl{
1130175942Sscottl	if (hba->bar0_res)
1131175942Sscottl		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1132175942Sscottl			hba->bar0_rid, hba->bar0_res);
1133175942Sscottl}
1134175942Sscottl
1135175942Sscottlstatic void hptiop_release_pci_res_mv(struct hpt_iop_hba *hba)
1136175942Sscottl{
1137175942Sscottl	if (hba->bar0_res)
1138175942Sscottl		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1139175942Sscottl			hba->bar0_rid, hba->bar0_res);
1140175942Sscottl	if (hba->bar2_res)
1141175942Sscottl		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1142175942Sscottl			hba->bar2_rid, hba->bar2_res);
1143175942Sscottl}
1144175942Sscottl
1145175942Sscottlstatic int hptiop_internal_memalloc_mv(struct hpt_iop_hba *hba)
1146175942Sscottl{
1147175942Sscottl	if (bus_dma_tag_create(hba->parent_dmat,
1148175942Sscottl				1,
1149175942Sscottl				0,
1150175942Sscottl				BUS_SPACE_MAXADDR_32BIT,
1151175942Sscottl				BUS_SPACE_MAXADDR,
1152175942Sscottl				NULL, NULL,
1153175942Sscottl				0x800 - 0x8,
1154175942Sscottl				1,
1155175942Sscottl				BUS_SPACE_MAXSIZE_32BIT,
1156175942Sscottl				BUS_DMA_ALLOCNOW,
1157175942Sscottl#if __FreeBSD_version > 502000
1158175942Sscottl				NULL,
1159175942Sscottl				NULL,
1160175942Sscottl#endif
1161175942Sscottl                           		&hba->ctlcfg_dmat)) {
1162175942Sscottl		device_printf(hba->pcidev, "alloc ctlcfg_dmat failed\n");
1163175942Sscottl		return -1;
1164175942Sscottl	}
1165175942Sscottl
1166175942Sscottl	if (bus_dmamem_alloc(hba->ctlcfg_dmat, (void **)&hba->ctlcfg_ptr,
1167175942Sscottl#if __FreeBSD_version>501000
1168175942Sscottl		BUS_DMA_WAITOK | BUS_DMA_COHERENT,
1169175942Sscottl#else
1170175942Sscottl		BUS_DMA_WAITOK,
1171175942Sscottl#endif
1172175942Sscottl		&hba->ctlcfg_dmamap) != 0) {
1173175942Sscottl			device_printf(hba->pcidev,
1174175942Sscottl					"bus_dmamem_alloc failed!\n");
1175175942Sscottl			bus_dma_tag_destroy(hba->ctlcfg_dmat);
1176175942Sscottl			return -1;
1177175942Sscottl	}
1178175942Sscottl
1179175942Sscottl	if (bus_dmamap_load(hba->ctlcfg_dmat,
1180175942Sscottl			hba->ctlcfg_dmamap, hba->ctlcfg_ptr,
1181175942Sscottl			MVIOP_IOCTLCFG_SIZE,
1182175942Sscottl			hptiop_mv_map_ctlcfg, hba, 0)) {
1183175942Sscottl		device_printf(hba->pcidev, "bus_dmamap_load failed!\n");
1184175942Sscottl		if (hba->ctlcfg_dmat)
1185175942Sscottl			bus_dmamem_free(hba->ctlcfg_dmat,
1186175942Sscottl				hba->ctlcfg_ptr, hba->ctlcfg_dmamap);
1187175942Sscottl			bus_dma_tag_destroy(hba->ctlcfg_dmat);
1188175942Sscottl		return -1;
1189175942Sscottl	}
1190175942Sscottl
1191175942Sscottl	return 0;
1192175942Sscottl}
1193175942Sscottl
1194175942Sscottlstatic int hptiop_internal_memfree_mv(struct hpt_iop_hba *hba)
1195175942Sscottl{
1196175942Sscottl	if (hba->ctlcfg_dmat) {
1197175942Sscottl		bus_dmamap_unload(hba->ctlcfg_dmat, hba->ctlcfg_dmamap);
1198175942Sscottl		bus_dmamem_free(hba->ctlcfg_dmat,
1199175942Sscottl					hba->ctlcfg_ptr, hba->ctlcfg_dmamap);
1200175942Sscottl		bus_dma_tag_destroy(hba->ctlcfg_dmat);
1201175942Sscottl	}
1202175942Sscottl
1203175942Sscottl	return 0;
1204175942Sscottl}
1205175942Sscottl
1206169412Sscottl/*
1207169412Sscottl * CAM driver interface
1208169412Sscottl */
1209169412Sscottlstatic device_method_t driver_methods[] = {
1210169412Sscottl	/* Device interface */
1211169412Sscottl	DEVMETHOD(device_probe,     hptiop_probe),
1212169412Sscottl	DEVMETHOD(device_attach,    hptiop_attach),
1213169412Sscottl	DEVMETHOD(device_detach,    hptiop_detach),
1214169412Sscottl	DEVMETHOD(device_shutdown,  hptiop_shutdown),
1215169412Sscottl	{ 0, 0 }
1216169412Sscottl};
1217169412Sscottl
1218175942Sscottlstatic struct hptiop_adapter_ops hptiop_itl_ops = {
1219175942Sscottl	.iop_wait_ready    = hptiop_wait_ready_itl,
1220175942Sscottl	.internal_memalloc = 0,
1221175942Sscottl	.internal_memfree  = 0,
1222175942Sscottl	.alloc_pci_res     = hptiop_alloc_pci_res_itl,
1223175942Sscottl	.release_pci_res   = hptiop_release_pci_res_itl,
1224175942Sscottl	.enable_intr       = hptiop_enable_intr_itl,
1225175942Sscottl	.disable_intr      = hptiop_disable_intr_itl,
1226175942Sscottl	.get_config        = hptiop_get_config_itl,
1227175942Sscottl	.set_config        = hptiop_set_config_itl,
1228175942Sscottl	.iop_intr          = hptiop_intr_itl,
1229175942Sscottl	.post_msg          = hptiop_post_msg_itl,
1230175942Sscottl	.post_req          = hptiop_post_req_itl,
1231175942Sscottl	.do_ioctl          = hptiop_do_ioctl_itl,
1232175942Sscottl};
1233175942Sscottl
1234175942Sscottlstatic struct hptiop_adapter_ops hptiop_mv_ops = {
1235175942Sscottl	.iop_wait_ready    = hptiop_wait_ready_mv,
1236175942Sscottl	.internal_memalloc = hptiop_internal_memalloc_mv,
1237175942Sscottl	.internal_memfree  = hptiop_internal_memfree_mv,
1238175942Sscottl	.alloc_pci_res     = hptiop_alloc_pci_res_mv,
1239175942Sscottl	.release_pci_res   = hptiop_release_pci_res_mv,
1240175942Sscottl	.enable_intr       = hptiop_enable_intr_mv,
1241175942Sscottl	.disable_intr      = hptiop_disable_intr_mv,
1242175942Sscottl	.get_config        = hptiop_get_config_mv,
1243175942Sscottl	.set_config        = hptiop_set_config_mv,
1244175942Sscottl	.iop_intr          = hptiop_intr_mv,
1245175942Sscottl	.post_msg          = hptiop_post_msg_mv,
1246175942Sscottl	.post_req          = hptiop_post_req_mv,
1247175942Sscottl	.do_ioctl          = hptiop_do_ioctl_mv,
1248175942Sscottl};
1249175942Sscottl
1250169412Sscottlstatic driver_t hptiop_pci_driver = {
1251169412Sscottl	driver_name,
1252169412Sscottl	driver_methods,
1253169412Sscottl	sizeof(struct hpt_iop_hba)
1254169412Sscottl};
1255169412Sscottl
1256169412SscottlDRIVER_MODULE(hptiop, pci, hptiop_pci_driver, hptiop_devclass, 0, 0);
1257169412Sscottl
1258169412Sscottlstatic int hptiop_probe(device_t dev)
1259169412Sscottl{
1260169412Sscottl	struct hpt_iop_hba *hba;
1261175942Sscottl	u_int32_t id;
1262175942Sscottl	static char buf[256];
1263175942Sscottl	int sas = 0;
1264175942Sscottl	struct hptiop_adapter_ops *ops;
1265169412Sscottl
1266175942Sscottl	if (pci_get_vendor(dev) != 0x1103)
1267175942Sscottl		return (ENXIO);
1268175942Sscottl
1269175942Sscottl	id = pci_get_device(dev);
1270175942Sscottl
1271175942Sscottl	switch (id) {
1272175942Sscottl		case 0x4320:
1273175942Sscottl			sas = 1;
1274175942Sscottl		case 0x3220:
1275175942Sscottl		case 0x3320:
1276175942Sscottl		case 0x3410:
1277175942Sscottl		case 0x3520:
1278175942Sscottl		case 0x3510:
1279175942Sscottl		case 0x3511:
1280175942Sscottl		case 0x3521:
1281175942Sscottl		case 0x3522:
1282175942Sscottl		case 0x3540:
1283175942Sscottl			ops = &hptiop_itl_ops;
1284175942Sscottl			break;
1285175942Sscottl		case 0x3120:
1286175942Sscottl		case 0x3122:
1287175942Sscottl		case 0x3020:
1288175942Sscottl			ops = &hptiop_mv_ops;
1289175942Sscottl			break;
1290175942Sscottl		default:
1291175942Sscottl			return (ENXIO);
1292169412Sscottl	}
1293175942Sscottl
1294175942Sscottl	device_printf(dev, "adapter at PCI %d:%d:%d, IRQ %d\n",
1295175942Sscottl		pci_get_bus(dev), pci_get_slot(dev),
1296175942Sscottl		pci_get_function(dev), pci_get_irq(dev));
1297175942Sscottl
1298175942Sscottl	sprintf(buf, "RocketRAID %x %s Controller\n",
1299175942Sscottl				id, sas ? "SAS" : "SATA");
1300175942Sscottl	device_set_desc_copy(dev, buf);
1301175942Sscottl
1302175942Sscottl	hba = (struct hpt_iop_hba *)device_get_softc(dev);
1303175942Sscottl	bzero(hba, sizeof(struct hpt_iop_hba));
1304175942Sscottl	hba->ops = ops;
1305175942Sscottl
1306175942Sscottl	KdPrint(("hba->ops=%p\n", hba->ops));
1307175942Sscottl	return 0;
1308169412Sscottl}
1309169412Sscottl
1310169412Sscottlstatic int hptiop_attach(device_t dev)
1311169412Sscottl{
1312175942Sscottl	struct hpt_iop_hba *hba = (struct hpt_iop_hba *)device_get_softc(dev);
1313169412Sscottl	struct hpt_iop_request_get_config  iop_config;
1314169412Sscottl	struct hpt_iop_request_set_config  set_config;
1315169412Sscottl	int rid = 0;
1316169412Sscottl	struct cam_devq *devq;
1317169412Sscottl	struct ccb_setasync ccb;
1318169412Sscottl	u_int32_t unit = device_get_unit(dev);
1319169412Sscottl
1320175942Sscottl	device_printf(dev, "%d RocketRAID 3xxx/4xxx controller driver %s\n",
1321175942Sscottl			unit, driver_version);
1322169412Sscottl
1323175942Sscottl	KdPrint(("hptiop: attach(%d, %d/%d/%d) ops=%p\n", unit,
1324175942Sscottl		pci_get_bus(dev), pci_get_slot(dev),
1325175942Sscottl		pci_get_function(dev), hba->ops));
1326175942Sscottl
1327169412Sscottl#if __FreeBSD_version >=440000
1328169412Sscottl	pci_enable_busmaster(dev);
1329169412Sscottl#endif
1330169412Sscottl	hba->pcidev = dev;
1331169412Sscottl	hba->pciunit = unit;
1332169412Sscottl
1333175942Sscottl	if (hba->ops->alloc_pci_res(hba))
1334169412Sscottl		return ENXIO;
1335169412Sscottl
1336175942Sscottl	if (hba->ops->iop_wait_ready(hba, 2000)) {
1337175942Sscottl		device_printf(dev, "adapter is not ready\n");
1338175942Sscottl		goto release_pci_res;
1339169412Sscottl	}
1340169412Sscottl
1341169412Sscottl#if (__FreeBSD_version >= 500000)
1342169412Sscottl	mtx_init(&hba->lock, "hptioplock", NULL, MTX_DEF);
1343169412Sscottl#endif
1344169412Sscottl
1345169412Sscottl	if (bus_dma_tag_create(NULL,/* parent */
1346169412Sscottl			1,  /* alignment */
1347169412Sscottl			0, /* boundary */
1348169412Sscottl			BUS_SPACE_MAXADDR,  /* lowaddr */
1349169412Sscottl			BUS_SPACE_MAXADDR,  /* highaddr */
1350169412Sscottl			NULL, NULL,         /* filter, filterarg */
1351169412Sscottl			BUS_SPACE_MAXSIZE_32BIT,    /* maxsize */
1352169412Sscottl			BUS_SPACE_UNRESTRICTED, /* nsegments */
1353169412Sscottl			BUS_SPACE_MAXSIZE_32BIT,    /* maxsegsize */
1354169412Sscottl			0,      /* flags */
1355169412Sscottl#if __FreeBSD_version>502000
1356169412Sscottl			NULL,   /* lockfunc */
1357169412Sscottl			NULL,       /* lockfuncarg */
1358169412Sscottl#endif
1359169412Sscottl			&hba->parent_dmat   /* tag */))
1360169412Sscottl	{
1361175942Sscottl		device_printf(dev, "alloc parent_dmat failed\n");
1362175942Sscottl		goto release_pci_res;
1363169412Sscottl	}
1364169412Sscottl
1365175942Sscottl	if (hba->ops->internal_memalloc) {
1366175942Sscottl		if (hba->ops->internal_memalloc(hba)) {
1367175942Sscottl			device_printf(dev, "alloc srb_dmat failed\n");
1368175942Sscottl			goto destroy_parent_tag;
1369175942Sscottl		}
1370175942Sscottl	}
1371175942Sscottl
1372175942Sscottl	if (hba->ops->get_config(hba, &iop_config)) {
1373175942Sscottl		device_printf(dev, "get iop config failed.\n");
1374175942Sscottl		goto get_config_failed;
1375175942Sscottl	}
1376175942Sscottl
1377175942Sscottl	hba->firmware_version = iop_config.firmware_version;
1378175942Sscottl	hba->interface_version = iop_config.interface_version;
1379175942Sscottl	hba->max_requests = iop_config.max_requests;
1380175942Sscottl	hba->max_devices = iop_config.max_devices;
1381175942Sscottl	hba->max_request_size = iop_config.request_size;
1382175942Sscottl	hba->max_sg_count = iop_config.max_sg_count;
1383175942Sscottl
1384169412Sscottl	if (bus_dma_tag_create(hba->parent_dmat,/* parent */
1385169412Sscottl			4,  /* alignment */
1386169412Sscottl			BUS_SPACE_MAXADDR_32BIT+1, /* boundary */
1387169412Sscottl			BUS_SPACE_MAXADDR,  /* lowaddr */
1388169412Sscottl			BUS_SPACE_MAXADDR,  /* highaddr */
1389169412Sscottl			NULL, NULL,         /* filter, filterarg */
1390169412Sscottl			PAGE_SIZE * (hba->max_sg_count-1),  /* maxsize */
1391169412Sscottl			hba->max_sg_count,  /* nsegments */
1392169412Sscottl			0x20000,    /* maxsegsize */
1393169412Sscottl			BUS_DMA_ALLOCNOW,       /* flags */
1394169412Sscottl#if __FreeBSD_version>502000
1395169412Sscottl			busdma_lock_mutex,  /* lockfunc */
1396169412Sscottl			&hba->lock,     /* lockfuncarg */
1397169412Sscottl#endif
1398169412Sscottl			&hba->io_dmat   /* tag */))
1399169412Sscottl	{
1400175942Sscottl		device_printf(dev, "alloc io_dmat failed\n");
1401175942Sscottl		goto get_config_failed;
1402169412Sscottl	}
1403169412Sscottl
1404169412Sscottl	if (bus_dma_tag_create(hba->parent_dmat,/* parent */
1405169412Sscottl			1,  /* alignment */
1406169412Sscottl			0, /* boundary */
1407169412Sscottl			BUS_SPACE_MAXADDR_32BIT,    /* lowaddr */
1408169412Sscottl			BUS_SPACE_MAXADDR,  /* highaddr */
1409169412Sscottl			NULL, NULL,         /* filter, filterarg */
1410169412Sscottl			HPT_SRB_MAX_SIZE * HPT_SRB_MAX_QUEUE_SIZE + 0x20,
1411169412Sscottl			1,  /* nsegments */
1412169412Sscottl			BUS_SPACE_MAXSIZE_32BIT,    /* maxsegsize */
1413169412Sscottl			0,      /* flags */
1414169412Sscottl#if __FreeBSD_version>502000
1415169412Sscottl			NULL,   /* lockfunc */
1416169412Sscottl			NULL,       /* lockfuncarg */
1417169412Sscottl#endif
1418169412Sscottl			&hba->srb_dmat  /* tag */))
1419169412Sscottl	{
1420175942Sscottl		device_printf(dev, "alloc srb_dmat failed\n");
1421175942Sscottl		goto destroy_io_dmat;
1422169412Sscottl	}
1423169412Sscottl
1424169412Sscottl	if (bus_dmamem_alloc(hba->srb_dmat, (void **)&hba->uncached_ptr,
1425169412Sscottl#if __FreeBSD_version>501000
1426175942Sscottl			BUS_DMA_WAITOK | BUS_DMA_COHERENT,
1427169412Sscottl#else
1428175942Sscottl			BUS_DMA_WAITOK,
1429169412Sscottl#endif
1430175942Sscottl			&hba->srb_dmamap) != 0)
1431169412Sscottl	{
1432175942Sscottl		device_printf(dev, "srb bus_dmamem_alloc failed!\n");
1433175942Sscottl		goto destroy_srb_dmat;
1434169412Sscottl	}
1435169412Sscottl
1436169412Sscottl	if (bus_dmamap_load(hba->srb_dmat,
1437169412Sscottl			hba->srb_dmamap, hba->uncached_ptr,
1438169412Sscottl			(HPT_SRB_MAX_SIZE * HPT_SRB_MAX_QUEUE_SIZE) + 0x20,
1439169412Sscottl			hptiop_map_srb, hba, 0))
1440169412Sscottl	{
1441175942Sscottl		device_printf(dev, "bus_dmamap_load failed!\n");
1442175942Sscottl		goto srb_dmamem_free;
1443169412Sscottl	}
1444169412Sscottl
1445169412Sscottl	if ((devq = cam_simq_alloc(hba->max_requests - 1 )) == NULL) {
1446175942Sscottl		device_printf(dev, "cam_simq_alloc failed\n");
1447175942Sscottl		goto srb_dmamap_unload;
1448169412Sscottl	}
1449175942Sscottl
1450175942Sscottl#if __FreeBSD_version <700000
1451169412Sscottl	hba->sim = cam_sim_alloc(hptiop_action, hptiop_poll, driver_name,
1452175942Sscottl			hba, unit, hba->max_requests - 1, 1, devq);
1453175942Sscottl#else
1454175942Sscottl	hba->sim = cam_sim_alloc(hptiop_action, hptiop_poll, driver_name,
1455169412Sscottl			hba, unit, &Giant, hba->max_requests - 1, 1, devq);
1456175942Sscottl#endif
1457169412Sscottl	if (!hba->sim) {
1458175942Sscottl		device_printf(dev, "cam_sim_alloc failed\n");
1459169412Sscottl		cam_simq_free(devq);
1460175942Sscottl		goto srb_dmamap_unload;
1461169412Sscottl	}
1462175942Sscottl#if __FreeBSD_version <700000
1463175942Sscottl	if (xpt_bus_register(hba->sim, 0) != CAM_SUCCESS)
1464175942Sscottl#else
1465175942Sscottl	if (xpt_bus_register(hba->sim, dev, 0) != CAM_SUCCESS)
1466175942Sscottl#endif
1467175942Sscottl	{
1468175942Sscottl		device_printf(dev, "xpt_bus_register failed\n");
1469175942Sscottl		goto free_cam_sim;
1470169412Sscottl	}
1471169412Sscottl
1472169412Sscottl	if (xpt_create_path(&hba->path, /*periph */ NULL,
1473169412Sscottl			cam_sim_path(hba->sim), CAM_TARGET_WILDCARD,
1474175942Sscottl			CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
1475175942Sscottl		device_printf(dev, "xpt_create_path failed\n");
1476175942Sscottl		goto deregister_xpt_bus;
1477169412Sscottl	}
1478169412Sscottl
1479169412Sscottl	bzero(&set_config, sizeof(set_config));
1480175942Sscottl	set_config.iop_id = unit;
1481169412Sscottl	set_config.vbus_id = cam_sim_path(hba->sim);
1482169412Sscottl	set_config.max_host_request_size = HPT_SRB_MAX_REQ_SIZE;
1483169412Sscottl
1484175942Sscottl	if (hba->ops->set_config(hba, &set_config)) {
1485175942Sscottl		device_printf(dev, "set iop config failed.\n");
1486175942Sscottl		goto free_hba_path;
1487169412Sscottl	}
1488169412Sscottl
1489169412Sscottl	xpt_setup_ccb(&ccb.ccb_h, hba->path, /*priority*/5);
1490169412Sscottl	ccb.ccb_h.func_code = XPT_SASYNC_CB;
1491169412Sscottl	ccb.event_enable = (AC_FOUND_DEVICE | AC_LOST_DEVICE);
1492169412Sscottl	ccb.callback = hptiop_async;
1493169412Sscottl	ccb.callback_arg = hba->sim;
1494169412Sscottl	xpt_action((union ccb *)&ccb);
1495169412Sscottl
1496169412Sscottl	rid = 0;
1497169412Sscottl	if ((hba->irq_res = bus_alloc_resource(hba->pcidev, SYS_RES_IRQ,
1498169412Sscottl			&rid, 0, ~0ul, 1, RF_SHAREABLE | RF_ACTIVE)) == NULL) {
1499175942Sscottl		device_printf(dev, "allocate irq failed!\n");
1500175942Sscottl		goto free_hba_path;
1501169412Sscottl	}
1502169412Sscottl
1503175942Sscottl#if __FreeBSD_version <700000
1504169412Sscottl	if (bus_setup_intr(hba->pcidev, hba->irq_res, INTR_TYPE_CAM,
1505175942Sscottl				hptiop_pci_intr, hba, &hba->irq_handle))
1506175942Sscottl#else
1507175942Sscottl	if (bus_setup_intr(hba->pcidev, hba->irq_res, INTR_TYPE_CAM,
1508175942Sscottl				NULL, hptiop_pci_intr, hba, &hba->irq_handle))
1509175942Sscottl#endif
1510175942Sscottl	{
1511175942Sscottl		device_printf(dev, "allocate intr function failed!\n");
1512175942Sscottl		goto free_irq_resource;
1513169412Sscottl	}
1514169412Sscottl
1515175942Sscottl	if (hptiop_send_sync_msg(hba,
1516175942Sscottl			IOPMU_INBOUND_MSG0_START_BACKGROUND_TASK, 5000)) {
1517175942Sscottl		device_printf(dev, "fail to start background task\n");
1518175942Sscottl		goto teartown_irq_resource;
1519169412Sscottl	}
1520169412Sscottl
1521175942Sscottl	hba->ops->enable_intr(hba);
1522175942Sscottl
1523169412Sscottl	hba->ioctl_dev = make_dev(&hptiop_cdevsw, unit,
1524169412Sscottl				UID_ROOT, GID_WHEEL /*GID_OPERATOR*/,
1525169412Sscottl				S_IRUSR | S_IWUSR, "%s%d", driver_name, unit);
1526169412Sscottl
1527169412Sscottl#if __FreeBSD_version < 503000
1528169412Sscottl	hba->ioctl_dev->si_drv1 = hba;
1529169412Sscottl#endif
1530169412Sscottl
1531169412Sscottl	return 0;
1532175942Sscottl
1533175942Sscottl
1534175942Sscottlteartown_irq_resource:
1535175942Sscottl	bus_teardown_intr(dev, hba->irq_res, hba->irq_handle);
1536175942Sscottl
1537175942Sscottlfree_irq_resource:
1538175942Sscottl	bus_release_resource(dev, SYS_RES_IRQ, 0, hba->irq_res);
1539175942Sscottl
1540175942Sscottlfree_hba_path:
1541175942Sscottl	xpt_free_path(hba->path);
1542175942Sscottl
1543175942Sscottlderegister_xpt_bus:
1544175942Sscottl	xpt_bus_deregister(cam_sim_path(hba->sim));
1545175942Sscottl
1546175942Sscottlfree_cam_sim:
1547175942Sscottl	cam_sim_free(hba->sim, /*free devq*/ TRUE);
1548175942Sscottl
1549175942Sscottlsrb_dmamap_unload:
1550175942Sscottl	if (hba->uncached_ptr)
1551175942Sscottl		bus_dmamap_unload(hba->srb_dmat, hba->srb_dmamap);
1552175942Sscottl
1553175942Sscottlsrb_dmamem_free:
1554175942Sscottl	if (hba->uncached_ptr)
1555175942Sscottl		bus_dmamem_free(hba->srb_dmat,
1556175942Sscottl			hba->uncached_ptr, hba->srb_dmamap);
1557175942Sscottl
1558175942Sscottldestroy_srb_dmat:
1559175942Sscottl	if (hba->srb_dmat)
1560175942Sscottl		bus_dma_tag_destroy(hba->srb_dmat);
1561175942Sscottl
1562175942Sscottldestroy_io_dmat:
1563175942Sscottl	if (hba->io_dmat)
1564175942Sscottl		bus_dma_tag_destroy(hba->io_dmat);
1565175942Sscottl
1566175942Sscottlget_config_failed:
1567175942Sscottl	if (hba->ops->internal_memfree)
1568175942Sscottl		hba->ops->internal_memfree(hba);
1569175942Sscottl
1570175942Sscottldestroy_parent_tag:
1571175942Sscottl	if (hba->parent_dmat)
1572175942Sscottl		bus_dma_tag_destroy(hba->parent_dmat);
1573175942Sscottl
1574175942Sscottlrelease_pci_res:
1575175942Sscottl	if (hba->ops->release_pci_res)
1576175942Sscottl		hba->ops->release_pci_res(hba);
1577175942Sscottl
1578175942Sscottl	return ENXIO;
1579169412Sscottl}
1580169412Sscottl
1581169412Sscottlstatic int hptiop_detach(device_t dev)
1582169412Sscottl{
1583169412Sscottl	struct hpt_iop_hba * hba = (struct hpt_iop_hba *)device_get_softc(dev);
1584169412Sscottl	int i;
1585169412Sscottl	int error = EBUSY;
1586169412Sscottl
1587169412Sscottl	hptiop_lock_adapter(hba);
1588175942Sscottl	for (i = 0; i < hba->max_devices; i++)
1589175942Sscottl		if (hptiop_os_query_remove_device(hba, i)) {
1590175942Sscottl			device_printf(dev, "%d file system is busy. id=%d",
1591169412Sscottl						hba->pciunit, i);
1592169412Sscottl			goto out;
1593169412Sscottl		}
1594169412Sscottl
1595169412Sscottl	if ((error = hptiop_shutdown(dev)) != 0)
1596169412Sscottl		goto out;
1597175942Sscottl	if (hptiop_send_sync_msg(hba,
1598175942Sscottl		IOPMU_INBOUND_MSG0_STOP_BACKGROUND_TASK, 60000))
1599169412Sscottl		goto out;
1600169412Sscottl
1601169412Sscottl	hptiop_release_resource(hba);
1602169412Sscottl	error = 0;
1603169412Sscottlout:
1604169412Sscottl	hptiop_unlock_adapter(hba);
1605169412Sscottl	return error;
1606169412Sscottl}
1607169412Sscottl
1608169412Sscottlstatic int hptiop_shutdown(device_t dev)
1609169412Sscottl{
1610169412Sscottl	struct hpt_iop_hba * hba = (struct hpt_iop_hba *)device_get_softc(dev);
1611169412Sscottl
1612169412Sscottl	int error = 0;
1613169412Sscottl
1614169412Sscottl	if (hba->flag & HPT_IOCTL_FLAG_OPEN) {
1615175942Sscottl		device_printf(dev, "%d device is busy", hba->pciunit);
1616169412Sscottl		return EBUSY;
1617169412Sscottl	}
1618175942Sscottl
1619175942Sscottl	hba->ops->disable_intr(hba);
1620175942Sscottl
1621175942Sscottl	if (hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_SHUTDOWN, 60000))
1622169412Sscottl		error = EBUSY;
1623169412Sscottl
1624169412Sscottl	return error;
1625169412Sscottl}
1626169412Sscottl
1627169412Sscottlstatic void hptiop_pci_intr(void *arg)
1628169412Sscottl{
1629169412Sscottl	struct hpt_iop_hba * hba = (struct hpt_iop_hba *)arg;
1630169412Sscottl	hptiop_lock_adapter(hba);
1631175942Sscottl	hba->ops->iop_intr(hba);
1632169412Sscottl	hptiop_unlock_adapter(hba);
1633169412Sscottl}
1634169412Sscottl
1635169412Sscottlstatic void hptiop_poll(struct cam_sim *sim)
1636169412Sscottl{
1637169412Sscottl	hptiop_pci_intr(cam_sim_softc(sim));
1638169412Sscottl}
1639169412Sscottl
1640169412Sscottlstatic void hptiop_async(void * callback_arg, u_int32_t code,
1641169412Sscottl					struct cam_path * path, void * arg)
1642169412Sscottl{
1643169412Sscottl}
1644169412Sscottl
1645175942Sscottlstatic void hptiop_enable_intr_itl(struct hpt_iop_hba *hba)
1646169412Sscottl{
1647175942Sscottl	BUS_SPACE_WRT4_ITL(outbound_intmask,
1648169412Sscottl		~(IOPMU_OUTBOUND_INT_POSTQUEUE | IOPMU_OUTBOUND_INT_MSG0));
1649169412Sscottl}
1650169412Sscottl
1651175942Sscottlstatic void hptiop_enable_intr_mv(struct hpt_iop_hba *hba)
1652169412Sscottl{
1653169412Sscottl	u_int32_t int_mask;
1654169412Sscottl
1655175942Sscottl	int_mask = BUS_SPACE_RD4_MV0(outbound_intmask);
1656175942Sscottl
1657175942Sscottl	int_mask |= MVIOP_MU_OUTBOUND_INT_POSTQUEUE
1658175942Sscottl			| MVIOP_MU_OUTBOUND_INT_MSG;
1659175942Sscottl    	BUS_SPACE_WRT4_MV0(outbound_intmask,int_mask);
1660169412Sscottl}
1661169412Sscottl
1662175942Sscottlstatic void hptiop_disable_intr_itl(struct hpt_iop_hba *hba)
1663175942Sscottl{
1664175942Sscottl	u_int32_t int_mask;
1665175942Sscottl
1666175942Sscottl	int_mask = BUS_SPACE_RD4_ITL(outbound_intmask);
1667175942Sscottl
1668175942Sscottl	int_mask |= IOPMU_OUTBOUND_INT_POSTQUEUE | IOPMU_OUTBOUND_INT_MSG0;
1669175942Sscottl	BUS_SPACE_WRT4_ITL(outbound_intmask, int_mask);
1670175942Sscottl	BUS_SPACE_RD4_ITL(outbound_intstatus);
1671175942Sscottl}
1672175942Sscottl
1673175942Sscottlstatic void hptiop_disable_intr_mv(struct hpt_iop_hba *hba)
1674175942Sscottl{
1675175942Sscottl	u_int32_t int_mask;
1676175942Sscottl	int_mask = BUS_SPACE_RD4_MV0(outbound_intmask);
1677175942Sscottl
1678175942Sscottl	int_mask &= ~(MVIOP_MU_OUTBOUND_INT_MSG
1679175942Sscottl			| MVIOP_MU_OUTBOUND_INT_POSTQUEUE);
1680175942Sscottl	BUS_SPACE_WRT4_MV0(outbound_intmask,int_mask);
1681175942Sscottl	BUS_SPACE_RD4_MV0(outbound_intmask);
1682175942Sscottl}
1683175942Sscottl
1684169412Sscottlstatic int hptiop_reset_adapter(struct hpt_iop_hba * hba)
1685169412Sscottl{
1686175942Sscottl	return hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_RESET, 60000);
1687169412Sscottl}
1688169412Sscottl
1689169412Sscottlstatic void *hptiop_get_srb(struct hpt_iop_hba * hba)
1690169412Sscottl{
1691169412Sscottl	struct hpt_iop_srb * srb;
1692169412Sscottl
1693169412Sscottl	if (hba->srb_list) {
1694169412Sscottl		srb = hba->srb_list;
1695169412Sscottl		hba->srb_list = srb->next;
1696175942Sscottl		return srb;
1697169412Sscottl	}
1698169412Sscottl
1699175942Sscottl	return NULL;
1700169412Sscottl}
1701169412Sscottl
1702175942Sscottlstatic void hptiop_free_srb(struct hpt_iop_hba *hba, struct hpt_iop_srb *srb)
1703169412Sscottl{
1704169412Sscottl	srb->next = hba->srb_list;
1705169412Sscottl	hba->srb_list = srb;
1706169412Sscottl}
1707169412Sscottl
1708169412Sscottlstatic void hptiop_action(struct cam_sim *sim, union ccb *ccb)
1709169412Sscottl{
1710169412Sscottl	struct hpt_iop_hba * hba = (struct hpt_iop_hba *)cam_sim_softc(sim);
1711169412Sscottl	struct hpt_iop_srb * srb;
1712169412Sscottl
1713169412Sscottl	switch (ccb->ccb_h.func_code) {
1714169412Sscottl
1715169412Sscottl	case XPT_SCSI_IO:
1716169412Sscottl		hptiop_lock_adapter(hba);
1717169412Sscottl		if (ccb->ccb_h.target_lun != 0 ||
1718175942Sscottl			ccb->ccb_h.target_id >= hba->max_devices ||
1719169412Sscottl			(ccb->ccb_h.flags & CAM_CDB_PHYS))
1720169412Sscottl		{
1721169412Sscottl			ccb->ccb_h.status = CAM_TID_INVALID;
1722169412Sscottl			xpt_done(ccb);
1723169412Sscottl			goto scsi_done;
1724169412Sscottl		}
1725169412Sscottl
1726169412Sscottl		if ((srb = hptiop_get_srb(hba)) == NULL) {
1727175942Sscottl			device_printf(hba->pcidev, "srb allocated failed");
1728169412Sscottl			ccb->ccb_h.status = CAM_REQ_CMP_ERR;
1729169412Sscottl			xpt_done(ccb);
1730169412Sscottl			goto scsi_done;
1731169412Sscottl		}
1732169412Sscottl
1733169412Sscottl		srb->ccb = ccb;
1734169412Sscottl
1735169412Sscottl		if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_NONE)
1736169412Sscottl			hptiop_post_scsi_command(srb, NULL, 0, 0);
1737169412Sscottl		else if ((ccb->ccb_h.flags & CAM_SCATTER_VALID) == 0) {
1738169412Sscottl			if ((ccb->ccb_h.flags & CAM_DATA_PHYS) == 0) {
1739169412Sscottl				int error;
1740169412Sscottl
1741169412Sscottl				error = bus_dmamap_load(hba->io_dmat,
1742175942Sscottl						srb->dma_map,
1743175942Sscottl						ccb->csio.data_ptr,
1744175942Sscottl						ccb->csio.dxfer_len,
1745175942Sscottl						hptiop_post_scsi_command,
1746175942Sscottl						srb, 0);
1747169412Sscottl
1748169412Sscottl				if (error && error != EINPROGRESS) {
1749175942Sscottl					device_printf(hba->pcidev,
1750175942Sscottl						"%d bus_dmamap_load error %d",
1751175942Sscottl						hba->pciunit, error);
1752169412Sscottl					xpt_freeze_simq(hba->sim, 1);
1753169412Sscottl					ccb->ccb_h.status = CAM_REQ_CMP_ERR;
1754169412Sscottlinvalid:
1755169412Sscottl					hptiop_free_srb(hba, srb);
1756169412Sscottl					xpt_done(ccb);
1757169412Sscottl					goto scsi_done;
1758169412Sscottl				}
1759169412Sscottl			}
1760169412Sscottl			else {
1761175942Sscottl				device_printf(hba->pcidev,
1762175942Sscottl					"CAM_DATA_PHYS not supported");
1763169412Sscottl				ccb->ccb_h.status = CAM_REQ_CMP_ERR;
1764169412Sscottl				goto invalid;
1765169412Sscottl			}
1766169412Sscottl		}
1767169412Sscottl		else {
1768169412Sscottl			struct bus_dma_segment *segs;
1769169412Sscottl
1770169412Sscottl			if ((ccb->ccb_h.flags & CAM_SG_LIST_PHYS) == 0 ||
1771169412Sscottl				(ccb->ccb_h.flags & CAM_DATA_PHYS) != 0) {
1772175942Sscottl				device_printf(hba->pcidev, "SCSI cmd failed");
1773169412Sscottl				ccb->ccb_h.status=CAM_PROVIDE_FAIL;
1774169412Sscottl				goto invalid;
1775169412Sscottl			}
1776169412Sscottl
1777169412Sscottl			segs = (struct bus_dma_segment *)ccb->csio.data_ptr;
1778169412Sscottl			hptiop_post_scsi_command(srb, segs,
1779169412Sscottl						ccb->csio.sglist_cnt, 0);
1780169412Sscottl		}
1781169412Sscottl
1782169412Sscottlscsi_done:
1783169412Sscottl		hptiop_unlock_adapter(hba);
1784169412Sscottl		return;
1785169412Sscottl
1786169412Sscottl	case XPT_RESET_BUS:
1787175942Sscottl		device_printf(hba->pcidev, "reset adapter");
1788169412Sscottl		hptiop_lock_adapter(hba);
1789169412Sscottl		hba->msg_done = 0;
1790169412Sscottl		hptiop_reset_adapter(hba);
1791169412Sscottl		hptiop_unlock_adapter(hba);
1792169412Sscottl		break;
1793169412Sscottl
1794169412Sscottl	case XPT_GET_TRAN_SETTINGS:
1795169412Sscottl	case XPT_SET_TRAN_SETTINGS:
1796169412Sscottl		ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
1797169412Sscottl		break;
1798169412Sscottl
1799169412Sscottl	case XPT_CALC_GEOMETRY:
1800169412Sscottl		ccb->ccg.heads = 255;
1801169412Sscottl		ccb->ccg.secs_per_track = 63;
1802169412Sscottl		ccb->ccg.cylinders = ccb->ccg.volume_size /
1803169412Sscottl				(ccb->ccg.heads * ccb->ccg.secs_per_track);
1804169412Sscottl		ccb->ccb_h.status = CAM_REQ_CMP;
1805169412Sscottl		break;
1806169412Sscottl
1807169412Sscottl	case XPT_PATH_INQ:
1808169412Sscottl	{
1809169412Sscottl		struct ccb_pathinq *cpi = &ccb->cpi;
1810169412Sscottl
1811169412Sscottl		cpi->version_num = 1;
1812169412Sscottl		cpi->hba_inquiry = PI_SDTR_ABLE;
1813169412Sscottl		cpi->target_sprt = 0;
1814169412Sscottl		cpi->hba_misc = PIM_NOBUSRESET;
1815169412Sscottl		cpi->hba_eng_cnt = 0;
1816175942Sscottl		cpi->max_target = hba->max_devices;
1817169412Sscottl		cpi->max_lun = 0;
1818169412Sscottl		cpi->unit_number = cam_sim_unit(sim);
1819169412Sscottl		cpi->bus_id = cam_sim_bus(sim);
1820175942Sscottl		cpi->initiator_id = hba->max_devices;
1821169412Sscottl		cpi->base_transfer_speed = 3300;
1822169412Sscottl
1823169412Sscottl		strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
1824169412Sscottl		strncpy(cpi->hba_vid, "HPT   ", HBA_IDLEN);
1825169412Sscottl		strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
1826169412Sscottl		cpi->ccb_h.status = CAM_REQ_CMP;
1827169412Sscottl		break;
1828169412Sscottl	}
1829169412Sscottl
1830169412Sscottl	default:
1831169412Sscottl		ccb->ccb_h.status = CAM_REQ_INVALID;
1832169412Sscottl		break;
1833169412Sscottl	}
1834169412Sscottl
1835169412Sscottl	xpt_done(ccb);
1836169412Sscottl	return;
1837169412Sscottl}
1838169412Sscottl
1839175942Sscottlstatic void hptiop_post_req_itl(struct hpt_iop_hba *hba,
1840175942Sscottl				struct hpt_iop_srb *srb,
1841175942Sscottl				bus_dma_segment_t *segs, int nsegs)
1842169412Sscottl{
1843169412Sscottl	int idx;
1844169412Sscottl	union ccb *ccb = srb->ccb;
1845169412Sscottl	u_int8_t *cdb;
1846169412Sscottl
1847175942Sscottl	if (ccb->ccb_h.flags & CAM_CDB_POINTER)
1848175942Sscottl		cdb = ccb->csio.cdb_io.cdb_ptr;
1849175942Sscottl	else
1850175942Sscottl		cdb = ccb->csio.cdb_io.cdb_bytes;
1851169412Sscottl
1852175942Sscottl	KdPrint(("ccb=%p %x-%x-%x\n",
1853175942Sscottl		ccb, *(u_int32_t *)cdb, *((u_int32_t *)cdb+1), *((u_int32_t *)cdb+2)));
1854169412Sscottl
1855169412Sscottl	if (srb->srb_flag & HPT_SRB_FLAG_HIGH_MEM_ACESS) {
1856175942Sscottl		u_int32_t iop_req32;
1857175942Sscottl		struct hpt_iop_request_scsi_command req;
1858169412Sscottl
1859175942Sscottl		iop_req32 = BUS_SPACE_RD4_ITL(inbound_queue);
1860175942Sscottl
1861175942Sscottl		if (iop_req32 == IOPMU_QUEUE_EMPTY) {
1862175942Sscottl			device_printf(hba->pcidev, "invaild req offset\n");
1863175942Sscottl			ccb->ccb_h.status = CAM_BUSY;
1864175942Sscottl			bus_dmamap_unload(hba->io_dmat, srb->dma_map);
1865175942Sscottl			hptiop_free_srb(hba, srb);
1866175942Sscottl			xpt_done(ccb);
1867175942Sscottl			return;
1868169412Sscottl		}
1869175942Sscottl
1870175942Sscottl		if (ccb->csio.dxfer_len && nsegs > 0) {
1871175942Sscottl			struct hpt_iopsg *psg = req.sg_list;
1872175942Sscottl			for (idx = 0; idx < nsegs; idx++, psg++) {
1873175942Sscottl				psg->pci_address = (u_int64_t)segs[idx].ds_addr;
1874175942Sscottl				psg->size = segs[idx].ds_len;
1875175942Sscottl				psg->eot = 0;
1876175942Sscottl			}
1877175942Sscottl			psg[-1].eot = 1;
1878175942Sscottl		}
1879175942Sscottl
1880175942Sscottl		bcopy(cdb, req.cdb, ccb->csio.cdb_len);
1881175942Sscottl
1882175942Sscottl		req.header.size = offsetof(struct hpt_iop_request_scsi_command, sg_list)
1883175942Sscottl				+ nsegs*sizeof(struct hpt_iopsg);
1884175942Sscottl		req.header.type = IOP_REQUEST_TYPE_SCSI_COMMAND;
1885175942Sscottl		req.header.flags = 0;
1886175942Sscottl		req.header.result = IOP_RESULT_PENDING;
1887175942Sscottl		req.header.context = (u_int64_t)(unsigned long)srb;
1888175942Sscottl		req.dataxfer_length = ccb->csio.dxfer_len;
1889175942Sscottl		req.channel =  0;
1890175942Sscottl		req.target =  ccb->ccb_h.target_id;
1891175942Sscottl		req.lun =  ccb->ccb_h.target_lun;
1892175942Sscottl
1893175942Sscottl		bus_space_write_region_1(hba->bar0t, hba->bar0h, iop_req32,
1894175942Sscottl			(u_int8_t *)&req, req.header.size);
1895175942Sscottl
1896175942Sscottl		if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
1897175942Sscottl			bus_dmamap_sync(hba->io_dmat,
1898175942Sscottl				srb->dma_map, BUS_DMASYNC_PREREAD);
1899175942Sscottl		}
1900175942Sscottl		else if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT)
1901175942Sscottl			bus_dmamap_sync(hba->io_dmat,
1902175942Sscottl				srb->dma_map, BUS_DMASYNC_PREWRITE);
1903175942Sscottl
1904175942Sscottl		BUS_SPACE_WRT4_ITL(inbound_queue,iop_req32);
1905175942Sscottl	} else {
1906175942Sscottl		struct hpt_iop_request_scsi_command *req;
1907175942Sscottl
1908169412Sscottl		req = (struct hpt_iop_request_scsi_command *)srb;
1909175942Sscottl		if (ccb->csio.dxfer_len && nsegs > 0) {
1910175942Sscottl			struct hpt_iopsg *psg = req->sg_list;
1911175942Sscottl			for (idx = 0; idx < nsegs; idx++, psg++) {
1912175942Sscottl				psg->pci_address =
1913175942Sscottl					(u_int64_t)segs[idx].ds_addr;
1914175942Sscottl				psg->size = segs[idx].ds_len;
1915175942Sscottl				psg->eot = 0;
1916175942Sscottl			}
1917175942Sscottl			psg[-1].eot = 1;
1918175942Sscottl		}
1919169412Sscottl
1920175942Sscottl		bcopy(cdb, req->cdb, ccb->csio.cdb_len);
1921175942Sscottl
1922175942Sscottl		req->header.type = IOP_REQUEST_TYPE_SCSI_COMMAND;
1923175942Sscottl		req->header.result = IOP_RESULT_PENDING;
1924175942Sscottl		req->dataxfer_length = ccb->csio.dxfer_len;
1925175942Sscottl		req->channel =  0;
1926175942Sscottl		req->target =  ccb->ccb_h.target_id;
1927175942Sscottl		req->lun =  ccb->ccb_h.target_lun;
1928175942Sscottl		req->header.size = offsetof(struct hpt_iop_request_scsi_command, sg_list)
1929175942Sscottl			+ nsegs*sizeof(struct hpt_iopsg);
1930175942Sscottl		req->header.context = (u_int64_t)srb->index |
1931175942Sscottl						IOPMU_QUEUE_ADDR_HOST_BIT;
1932175942Sscottl		req->header.flags = IOP_REQUEST_FLAG_OUTPUT_CONTEXT;
1933175942Sscottl
1934175942Sscottl		if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
1935175942Sscottl			bus_dmamap_sync(hba->io_dmat,
1936175942Sscottl				srb->dma_map, BUS_DMASYNC_PREREAD);
1937175942Sscottl		}else if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) {
1938175942Sscottl			bus_dmamap_sync(hba->io_dmat,
1939175942Sscottl				srb->dma_map, BUS_DMASYNC_PREWRITE);
1940175942Sscottl		}
1941175942Sscottl
1942175942Sscottl		if (hba->firmware_version > 0x01020000
1943175942Sscottl			|| hba->interface_version > 0x01020000) {
1944175942Sscottl			u_int32_t size_bits;
1945175942Sscottl
1946175942Sscottl			if (req->header.size < 256)
1947175942Sscottl				size_bits = IOPMU_QUEUE_REQUEST_SIZE_BIT;
1948175942Sscottl			else if (req->header.size < 512)
1949175942Sscottl				size_bits = IOPMU_QUEUE_ADDR_HOST_BIT;
1950175942Sscottl			else
1951175942Sscottl				size_bits = IOPMU_QUEUE_REQUEST_SIZE_BIT
1952175942Sscottl						| IOPMU_QUEUE_ADDR_HOST_BIT;
1953175942Sscottl
1954175942Sscottl			BUS_SPACE_WRT4_ITL(inbound_queue,
1955175942Sscottl				(u_int32_t)srb->phy_addr | size_bits);
1956175942Sscottl		} else
1957175942Sscottl			BUS_SPACE_WRT4_ITL(inbound_queue, (u_int32_t)srb->phy_addr
1958175942Sscottl				|IOPMU_QUEUE_ADDR_HOST_BIT);
1959175942Sscottl	}
1960175942Sscottl}
1961175942Sscottl
1962175942Sscottlstatic void hptiop_post_req_mv(struct hpt_iop_hba *hba,
1963175942Sscottl				struct hpt_iop_srb *srb,
1964175942Sscottl				bus_dma_segment_t *segs, int nsegs)
1965175942Sscottl{
1966175942Sscottl	int idx, size;
1967175942Sscottl	union ccb *ccb = srb->ccb;
1968175942Sscottl	u_int8_t *cdb;
1969175942Sscottl	struct hpt_iop_request_scsi_command *req;
1970175942Sscottl	u_int64_t req_phy;
1971175942Sscottl
1972175942Sscottl    	req = (struct hpt_iop_request_scsi_command *)srb;
1973175942Sscottl	req_phy = srb->phy_addr;
1974175942Sscottl
1975169412Sscottl	if (ccb->csio.dxfer_len && nsegs > 0) {
1976169412Sscottl		struct hpt_iopsg *psg = req->sg_list;
1977169412Sscottl		for (idx = 0; idx < nsegs; idx++, psg++) {
1978169412Sscottl			psg->pci_address = (u_int64_t)segs[idx].ds_addr;
1979169412Sscottl			psg->size = segs[idx].ds_len;
1980169412Sscottl			psg->eot = 0;
1981169412Sscottl		}
1982169412Sscottl		psg[-1].eot = 1;
1983169412Sscottl	}
1984169412Sscottl	if (ccb->ccb_h.flags & CAM_CDB_POINTER)
1985169412Sscottl		cdb = ccb->csio.cdb_io.cdb_ptr;
1986169412Sscottl	else
1987169412Sscottl		cdb = ccb->csio.cdb_io.cdb_bytes;
1988169412Sscottl
1989169412Sscottl	bcopy(cdb, req->cdb, ccb->csio.cdb_len);
1990169412Sscottl	req->header.type = IOP_REQUEST_TYPE_SCSI_COMMAND;
1991169412Sscottl	req->header.result = IOP_RESULT_PENDING;
1992169412Sscottl	req->dataxfer_length = ccb->csio.dxfer_len;
1993175942Sscottl	req->channel = 0;
1994169412Sscottl	req->target =  ccb->ccb_h.target_id;
1995169412Sscottl	req->lun =  ccb->ccb_h.target_lun;
1996169412Sscottl	req->header.size = sizeof(struct hpt_iop_request_scsi_command)
1997175942Sscottl				- sizeof(struct hpt_iopsg)
1998175942Sscottl				+ nsegs * sizeof(struct hpt_iopsg);
1999169412Sscottl	if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
2000169412Sscottl		bus_dmamap_sync(hba->io_dmat,
2001175942Sscottl			srb->dma_map, BUS_DMASYNC_PREREAD);
2002169412Sscottl	}
2003169412Sscottl	else if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT)
2004169412Sscottl		bus_dmamap_sync(hba->io_dmat,
2005175942Sscottl			srb->dma_map, BUS_DMASYNC_PREWRITE);
2006175942Sscottl	req->header.context = (u_int64_t)srb->index
2007175942Sscottl					<< MVIOP_REQUEST_NUMBER_START_BIT
2008175942Sscottl					| MVIOP_CMD_TYPE_SCSI;
2009175942Sscottl	req->header.flags = IOP_REQUEST_FLAG_OUTPUT_CONTEXT;
2010175942Sscottl	size = req->header.size >> 8;
2011175942Sscottl	hptiop_mv_inbound_write(req_phy
2012175942Sscottl			| MVIOP_MU_QUEUE_ADDR_HOST_BIT
2013175942Sscottl			| (size > 3 ? 3 : size), hba);
2014169412Sscottl}
2015169412Sscottl
2016175942Sscottlstatic void hptiop_post_scsi_command(void *arg, bus_dma_segment_t *segs,
2017175942Sscottl					int nsegs, int error)
2018169412Sscottl{
2019175942Sscottl	struct hpt_iop_srb *srb = (struct hpt_iop_srb *)arg;
2020175942Sscottl	union ccb *ccb = srb->ccb;
2021175942Sscottl	struct hpt_iop_hba *hba = srb->hba;
2022169412Sscottl
2023175942Sscottl	if (error || nsegs > hba->max_sg_count) {
2024175942Sscottl		KdPrint(("hptiop: func_code=%x tid=%x lun=%x nsegs=%d\n",
2025175942Sscottl			ccb->ccb_h.func_code,
2026175942Sscottl			ccb->ccb_h.target_id,
2027175942Sscottl			ccb->ccb_h.target_lun, nsegs));
2028175942Sscottl		ccb->ccb_h.status = CAM_BUSY;
2029175942Sscottl		bus_dmamap_unload(hba->io_dmat, srb->dma_map);
2030169412Sscottl		hptiop_free_srb(hba, srb);
2031169412Sscottl		xpt_done(ccb);
2032175942Sscottl		return;
2033169412Sscottl	}
2034175942Sscottl
2035175942Sscottl	hba->ops->post_req(hba, srb, segs, nsegs);
2036169412Sscottl}
2037169412Sscottl
2038175942Sscottlstatic void hptiop_mv_map_ctlcfg(void *arg, bus_dma_segment_t *segs,
2039175942Sscottl				int nsegs, int error)
2040175942Sscottl{
2041175942Sscottl	struct hpt_iop_hba *hba = (struct hpt_iop_hba *)arg;
2042175942Sscottl	hba->ctlcfgcmd_phy = ((u_int64_t)segs->ds_addr + 0x1F)
2043175942Sscottl				& ~(u_int64_t)0x1F;
2044175942Sscottl	hba->ctlcfg_ptr = (u_int8_t *)(((unsigned long)hba->ctlcfg_ptr + 0x1F)
2045175942Sscottl				& ~0x1F);
2046175942Sscottl}
2047175942Sscottl
2048169412Sscottlstatic void hptiop_map_srb(void *arg, bus_dma_segment_t *segs,
2049175942Sscottl				int nsegs, int error)
2050169412Sscottl{
2051169412Sscottl	struct hpt_iop_hba * hba = (struct hpt_iop_hba *)arg;
2052169412Sscottl	bus_addr_t phy_addr = (segs->ds_addr + 0x1F) & ~(bus_addr_t)0x1F;
2053169412Sscottl	struct hpt_iop_srb *srb, *tmp_srb;
2054169412Sscottl	int i;
2055169412Sscottl
2056169412Sscottl	if (error || nsegs == 0) {
2057175942Sscottl		device_printf(hba->pcidev, "hptiop_map_srb error");
2058169412Sscottl		return;
2059169412Sscottl	}
2060169412Sscottl
2061169412Sscottl	/* map srb */
2062169412Sscottl	srb = (struct hpt_iop_srb *)
2063175942Sscottl		(((unsigned long)hba->uncached_ptr + 0x1F)
2064175942Sscottl		& ~(unsigned long)0x1F);
2065169412Sscottl
2066169412Sscottl	for (i = 0; i < HPT_SRB_MAX_QUEUE_SIZE; i++) {
2067169412Sscottl		tmp_srb = (struct hpt_iop_srb *)
2068169412Sscottl					((char *)srb + i * HPT_SRB_MAX_SIZE);
2069169412Sscottl		if (((unsigned long)tmp_srb & 0x1F) == 0) {
2070169412Sscottl			if (bus_dmamap_create(hba->io_dmat,
2071169412Sscottl						0, &tmp_srb->dma_map)) {
2072175942Sscottl				device_printf(hba->pcidev, "dmamap create failed");
2073169412Sscottl				return;
2074169412Sscottl			}
2075169412Sscottl
2076169412Sscottl			bzero(tmp_srb, sizeof(struct hpt_iop_srb));
2077169412Sscottl			tmp_srb->hba = hba;
2078169412Sscottl			tmp_srb->index = i;
2079175942Sscottl			if (hba->ctlcfg_ptr == 0) {/*itl iop*/
2080175942Sscottl				tmp_srb->phy_addr = (u_int64_t)(u_int32_t)
2081175942Sscottl							(phy_addr >> 5);
2082175942Sscottl				if (phy_addr & IOPMU_MAX_MEM_SUPPORT_MASK_32G)
2083175942Sscottl					tmp_srb->srb_flag =
2084175942Sscottl						HPT_SRB_FLAG_HIGH_MEM_ACESS;
2085175942Sscottl			} else {
2086175942Sscottl				tmp_srb->phy_addr = phy_addr;
2087175942Sscottl			}
2088175942Sscottl
2089169412Sscottl			hptiop_free_srb(hba, tmp_srb);
2090169412Sscottl			hba->srb[i] = tmp_srb;
2091169412Sscottl			phy_addr += HPT_SRB_MAX_SIZE;
2092169412Sscottl		}
2093169412Sscottl		else {
2094175942Sscottl			device_printf(hba->pcidev, "invalid alignment");
2095169412Sscottl			return;
2096169412Sscottl		}
2097169412Sscottl	}
2098169412Sscottl}
2099169412Sscottl
2100175942Sscottlstatic void hptiop_os_message_callback(struct hpt_iop_hba * hba, u_int32_t msg)
2101169412Sscottl{
2102169412Sscottl		hba->msg_done = 1;
2103169412Sscottl}
2104169412Sscottl
2105175942Sscottlstatic  int hptiop_os_query_remove_device(struct hpt_iop_hba * hba,
2106175942Sscottl						int target_id)
2107169412Sscottl{
2108169412Sscottl	struct cam_periph       *periph = NULL;
2109169412Sscottl	struct cam_path         *path;
2110169412Sscottl	int                     status, retval = 0;
2111169412Sscottl
2112169412Sscottl	status = xpt_create_path(&path, NULL, hba->sim->path_id, target_id, 0);
2113169412Sscottl
2114169412Sscottl	if (status == CAM_REQ_CMP) {
2115169412Sscottl		if ((periph = cam_periph_find(path, "da")) != NULL) {
2116169412Sscottl			if (periph->refcount >= 1) {
2117175942Sscottl				device_printf(hba->pcidev, "%d ,"
2118175942Sscottl					"target_id=0x%x,"
2119175942Sscottl					"refcount=%d",
2120169412Sscottl				    hba->pciunit, target_id, periph->refcount);
2121169412Sscottl				retval = -1;
2122169412Sscottl			}
2123169412Sscottl		}
2124169412Sscottl		xpt_free_path(path);
2125169412Sscottl	}
2126169412Sscottl	return retval;
2127169412Sscottl}
2128169412Sscottl
2129169412Sscottlstatic void hptiop_release_resource(struct hpt_iop_hba *hba)
2130169412Sscottl{
2131175942Sscottl	int i;
2132175942Sscottl	if (hba->path) {
2133175942Sscottl		struct ccb_setasync ccb;
2134169412Sscottl
2135169412Sscottl		xpt_setup_ccb(&ccb.ccb_h, hba->path, /*priority*/5);
2136169412Sscottl		ccb.ccb_h.func_code = XPT_SASYNC_CB;
2137169412Sscottl		ccb.event_enable = 0;
2138169412Sscottl		ccb.callback = hptiop_async;
2139169412Sscottl		ccb.callback_arg = hba->sim;
2140169412Sscottl		xpt_action((union ccb *)&ccb);
2141169412Sscottl		xpt_free_path(hba->path);
2142169412Sscottl	}
2143169412Sscottl
2144169412Sscottl	if (hba->sim) {
2145169412Sscottl		xpt_bus_deregister(cam_sim_path(hba->sim));
2146169412Sscottl		cam_sim_free(hba->sim, TRUE);
2147169412Sscottl	}
2148169412Sscottl
2149175942Sscottl	if (hba->ctlcfg_dmat) {
2150175942Sscottl		bus_dmamap_unload(hba->ctlcfg_dmat, hba->ctlcfg_dmamap);
2151175942Sscottl		bus_dmamem_free(hba->ctlcfg_dmat,
2152175942Sscottl					hba->ctlcfg_ptr, hba->ctlcfg_dmamap);
2153175942Sscottl		bus_dma_tag_destroy(hba->ctlcfg_dmat);
2154175942Sscottl	}
2155175942Sscottl
2156175942Sscottl	for (i = 0; i < HPT_SRB_MAX_QUEUE_SIZE; i++) {
2157175942Sscottl		struct hpt_iop_srb *srb = hba->srb[i];
2158175942Sscottl		if (srb->dma_map)
2159175942Sscottl			bus_dmamap_destroy(hba->io_dmat, srb->dma_map);
2160175942Sscottl	}
2161175942Sscottl
2162169412Sscottl	if (hba->srb_dmat) {
2163169412Sscottl		bus_dmamap_unload(hba->srb_dmat, hba->srb_dmamap);
2164175942Sscottl		bus_dmamap_destroy(hba->srb_dmat, hba->srb_dmamap);
2165169412Sscottl		bus_dma_tag_destroy(hba->srb_dmat);
2166169412Sscottl	}
2167169412Sscottl
2168169412Sscottl	if (hba->io_dmat)
2169169412Sscottl		bus_dma_tag_destroy(hba->io_dmat);
2170169412Sscottl
2171169412Sscottl	if (hba->parent_dmat)
2172169412Sscottl		bus_dma_tag_destroy(hba->parent_dmat);
2173169412Sscottl
2174169412Sscottl	if (hba->irq_handle)
2175169412Sscottl		bus_teardown_intr(hba->pcidev, hba->irq_res, hba->irq_handle);
2176169412Sscottl
2177169412Sscottl	if (hba->irq_res)
2178175942Sscottl		bus_release_resource(hba->pcidev, SYS_RES_IRQ,
2179175942Sscottl					0, hba->irq_res);
2180169412Sscottl
2181169412Sscottl	if (hba->bar0_res)
2182169412Sscottl		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
2183169412Sscottl					hba->bar0_rid, hba->bar0_res);
2184175942Sscottl	if (hba->bar2_res)
2185175942Sscottl		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
2186175942Sscottl					hba->bar2_rid, hba->bar2_res);
2187169412Sscottl	if (hba->ioctl_dev)
2188169412Sscottl		destroy_dev(hba->ioctl_dev);
2189169412Sscottl}
2190