xref: /freebsd/sys/dev/hptiop/hptiop.c (revision 5ca8e32633c4ffbbcd6762e5888b6a4ba0708c6c)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * HighPoint RR3xxx/4xxx RAID Driver for FreeBSD
5  * Copyright (C) 2007-2012 HighPoint Technologies, Inc. All Rights Reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include <sys/param.h>
30 #include <sys/types.h>
31 #include <sys/cons.h>
32 #include <sys/time.h>
33 #include <sys/systm.h>
34 
35 #include <sys/stat.h>
36 #include <sys/malloc.h>
37 #include <sys/conf.h>
38 #include <sys/libkern.h>
39 #include <sys/kernel.h>
40 
41 #include <sys/kthread.h>
42 #include <sys/mutex.h>
43 #include <sys/module.h>
44 
45 #include <sys/eventhandler.h>
46 #include <sys/bus.h>
47 #include <sys/taskqueue.h>
48 #include <sys/ioccom.h>
49 
50 #include <machine/resource.h>
51 #include <machine/bus.h>
52 #include <machine/stdarg.h>
53 #include <sys/rman.h>
54 
55 #include <vm/vm.h>
56 #include <vm/pmap.h>
57 
58 #include <dev/pci/pcireg.h>
59 #include <dev/pci/pcivar.h>
60 
61 
62 #include <cam/cam.h>
63 #include <cam/cam_ccb.h>
64 #include <cam/cam_sim.h>
65 #include <cam/cam_xpt_sim.h>
66 #include <cam/cam_debug.h>
67 #include <cam/cam_periph.h>
68 #include <cam/scsi/scsi_all.h>
69 #include <cam/scsi/scsi_message.h>
70 
71 
72 #include <dev/hptiop/hptiop.h>
73 
74 static const char driver_name[] = "hptiop";
75 static const char driver_version[] = "v1.9";
76 
77 static int hptiop_send_sync_msg(struct hpt_iop_hba *hba,
78 				u_int32_t msg, u_int32_t millisec);
79 static void hptiop_request_callback_itl(struct hpt_iop_hba *hba,
80 							u_int32_t req);
81 static void hptiop_request_callback_mv(struct hpt_iop_hba *hba, u_int64_t req);
82 static void hptiop_request_callback_mvfrey(struct hpt_iop_hba *hba,
83 							u_int32_t req);
84 static void hptiop_os_message_callback(struct hpt_iop_hba *hba, u_int32_t msg);
85 static int  hptiop_do_ioctl_itl(struct hpt_iop_hba *hba,
86 				struct hpt_iop_ioctl_param *pParams);
87 static int  hptiop_do_ioctl_mv(struct hpt_iop_hba *hba,
88 				struct hpt_iop_ioctl_param *pParams);
89 static int  hptiop_do_ioctl_mvfrey(struct hpt_iop_hba *hba,
90 				struct hpt_iop_ioctl_param *pParams);
91 static int  hptiop_rescan_bus(struct hpt_iop_hba *hba);
92 static int hptiop_alloc_pci_res_itl(struct hpt_iop_hba *hba);
93 static int hptiop_alloc_pci_res_mv(struct hpt_iop_hba *hba);
94 static int hptiop_alloc_pci_res_mvfrey(struct hpt_iop_hba *hba);
95 static int hptiop_get_config_itl(struct hpt_iop_hba *hba,
96 				struct hpt_iop_request_get_config *config);
97 static int hptiop_get_config_mv(struct hpt_iop_hba *hba,
98 				struct hpt_iop_request_get_config *config);
99 static int hptiop_get_config_mvfrey(struct hpt_iop_hba *hba,
100 				struct hpt_iop_request_get_config *config);
101 static int hptiop_set_config_itl(struct hpt_iop_hba *hba,
102 				struct hpt_iop_request_set_config *config);
103 static int hptiop_set_config_mv(struct hpt_iop_hba *hba,
104 				struct hpt_iop_request_set_config *config);
105 static int hptiop_set_config_mvfrey(struct hpt_iop_hba *hba,
106 				struct hpt_iop_request_set_config *config);
107 static int hptiop_internal_memalloc_mv(struct hpt_iop_hba *hba);
108 static int hptiop_internal_memalloc_mvfrey(struct hpt_iop_hba *hba);
109 static int hptiop_internal_memfree_itl(struct hpt_iop_hba *hba);
110 static int hptiop_internal_memfree_mv(struct hpt_iop_hba *hba);
111 static int hptiop_internal_memfree_mvfrey(struct hpt_iop_hba *hba);
112 static int  hptiop_post_ioctl_command_itl(struct hpt_iop_hba *hba,
113 			u_int32_t req32, struct hpt_iop_ioctl_param *pParams);
114 static int  hptiop_post_ioctl_command_mv(struct hpt_iop_hba *hba,
115 				struct hpt_iop_request_ioctl_command *req,
116 				struct hpt_iop_ioctl_param *pParams);
117 static int  hptiop_post_ioctl_command_mvfrey(struct hpt_iop_hba *hba,
118 				struct hpt_iop_request_ioctl_command *req,
119 				struct hpt_iop_ioctl_param *pParams);
120 static void hptiop_post_req_itl(struct hpt_iop_hba *hba,
121 				struct hpt_iop_srb *srb,
122 				bus_dma_segment_t *segs, int nsegs);
123 static void hptiop_post_req_mv(struct hpt_iop_hba *hba,
124 				struct hpt_iop_srb *srb,
125 				bus_dma_segment_t *segs, int nsegs);
126 static void hptiop_post_req_mvfrey(struct hpt_iop_hba *hba,
127 				struct hpt_iop_srb *srb,
128 				bus_dma_segment_t *segs, int nsegs);
129 static void hptiop_post_msg_itl(struct hpt_iop_hba *hba, u_int32_t msg);
130 static void hptiop_post_msg_mv(struct hpt_iop_hba *hba, u_int32_t msg);
131 static void hptiop_post_msg_mvfrey(struct hpt_iop_hba *hba, u_int32_t msg);
132 static void hptiop_enable_intr_itl(struct hpt_iop_hba *hba);
133 static void hptiop_enable_intr_mv(struct hpt_iop_hba *hba);
134 static void hptiop_enable_intr_mvfrey(struct hpt_iop_hba *hba);
135 static void hptiop_disable_intr_itl(struct hpt_iop_hba *hba);
136 static void hptiop_disable_intr_mv(struct hpt_iop_hba *hba);
137 static void hptiop_disable_intr_mvfrey(struct hpt_iop_hba *hba);
138 static void hptiop_free_srb(struct hpt_iop_hba *hba, struct hpt_iop_srb *srb);
139 static int  hptiop_os_query_remove_device(struct hpt_iop_hba *hba, int tid);
140 static int  hptiop_probe(device_t dev);
141 static int  hptiop_attach(device_t dev);
142 static int  hptiop_detach(device_t dev);
143 static int  hptiop_shutdown(device_t dev);
144 static void hptiop_action(struct cam_sim *sim, union ccb *ccb);
145 static void hptiop_poll(struct cam_sim *sim);
146 static void hptiop_async(void *callback_arg, u_int32_t code,
147 					struct cam_path *path, void *arg);
148 static void hptiop_pci_intr(void *arg);
149 static void hptiop_release_resource(struct hpt_iop_hba *hba);
150 static void hptiop_reset_adapter(void *argv);
151 static d_open_t hptiop_open;
152 static d_close_t hptiop_close;
153 static d_ioctl_t hptiop_ioctl;
154 
155 static struct cdevsw hptiop_cdevsw = {
156 	.d_open = hptiop_open,
157 	.d_close = hptiop_close,
158 	.d_ioctl = hptiop_ioctl,
159 	.d_name = driver_name,
160 	.d_version = D_VERSION,
161 };
162 
163 #define hba_from_dev(dev) \
164 	((struct hpt_iop_hba *)((dev)->si_drv1))
165 
166 #define BUS_SPACE_WRT4_ITL(offset, value) bus_space_write_4(hba->bar0t,\
167 		hba->bar0h, offsetof(struct hpt_iopmu_itl, offset), (value))
168 #define BUS_SPACE_RD4_ITL(offset) bus_space_read_4(hba->bar0t,\
169 		hba->bar0h, offsetof(struct hpt_iopmu_itl, offset))
170 
171 #define BUS_SPACE_WRT4_MV0(offset, value) bus_space_write_4(hba->bar0t,\
172 		hba->bar0h, offsetof(struct hpt_iopmv_regs, offset), value)
173 #define BUS_SPACE_RD4_MV0(offset) bus_space_read_4(hba->bar0t,\
174 		hba->bar0h, offsetof(struct hpt_iopmv_regs, offset))
175 #define BUS_SPACE_WRT4_MV2(offset, value) bus_space_write_4(hba->bar2t,\
176 		hba->bar2h, offsetof(struct hpt_iopmu_mv, offset), value)
177 #define BUS_SPACE_RD4_MV2(offset) bus_space_read_4(hba->bar2t,\
178 		hba->bar2h, offsetof(struct hpt_iopmu_mv, offset))
179 
180 #define BUS_SPACE_WRT4_MVFREY2(offset, value) bus_space_write_4(hba->bar2t,\
181 		hba->bar2h, offsetof(struct hpt_iopmu_mvfrey, offset), value)
182 #define BUS_SPACE_RD4_MVFREY2(offset) bus_space_read_4(hba->bar2t,\
183 		hba->bar2h, offsetof(struct hpt_iopmu_mvfrey, offset))
184 
185 static int hptiop_open(ioctl_dev_t dev, int flags,
186 					int devtype, ioctl_thread_t proc)
187 {
188 	struct hpt_iop_hba *hba = hba_from_dev(dev);
189 
190 	if (hba==NULL)
191 		return ENXIO;
192 	if (hba->flag & HPT_IOCTL_FLAG_OPEN)
193 		return EBUSY;
194 	hba->flag |= HPT_IOCTL_FLAG_OPEN;
195 	return 0;
196 }
197 
198 static int hptiop_close(ioctl_dev_t dev, int flags,
199 					int devtype, ioctl_thread_t proc)
200 {
201 	struct hpt_iop_hba *hba = hba_from_dev(dev);
202 	hba->flag &= ~(u_int32_t)HPT_IOCTL_FLAG_OPEN;
203 	return 0;
204 }
205 
206 static int hptiop_ioctl(ioctl_dev_t dev, u_long cmd, caddr_t data,
207 					int flags, ioctl_thread_t proc)
208 {
209 	int ret = EFAULT;
210 	struct hpt_iop_hba *hba = hba_from_dev(dev);
211 
212 	switch (cmd) {
213 	case HPT_DO_IOCONTROL:
214 		ret = hba->ops->do_ioctl(hba,
215 				(struct hpt_iop_ioctl_param *)data);
216 		break;
217 	case HPT_SCAN_BUS:
218 		ret = hptiop_rescan_bus(hba);
219 		break;
220 	}
221 	return ret;
222 }
223 
224 static u_int64_t hptiop_mv_outbound_read(struct hpt_iop_hba *hba)
225 {
226 	u_int64_t p;
227 	u_int32_t outbound_tail = BUS_SPACE_RD4_MV2(outbound_tail);
228 	u_int32_t outbound_head = BUS_SPACE_RD4_MV2(outbound_head);
229 
230 	if (outbound_tail != outbound_head) {
231 		bus_space_read_region_4(hba->bar2t, hba->bar2h,
232 			offsetof(struct hpt_iopmu_mv,
233 				outbound_q[outbound_tail]),
234 			(u_int32_t *)&p, 2);
235 
236 		outbound_tail++;
237 
238 		if (outbound_tail == MVIOP_QUEUE_LEN)
239 			outbound_tail = 0;
240 
241 		BUS_SPACE_WRT4_MV2(outbound_tail, outbound_tail);
242 		return p;
243 	} else
244 		return 0;
245 }
246 
247 static void hptiop_mv_inbound_write(u_int64_t p, struct hpt_iop_hba *hba)
248 {
249 	u_int32_t inbound_head = BUS_SPACE_RD4_MV2(inbound_head);
250 	u_int32_t head = inbound_head + 1;
251 
252 	if (head == MVIOP_QUEUE_LEN)
253 		head = 0;
254 
255 	bus_space_write_region_4(hba->bar2t, hba->bar2h,
256 			offsetof(struct hpt_iopmu_mv, inbound_q[inbound_head]),
257 			(u_int32_t *)&p, 2);
258 	BUS_SPACE_WRT4_MV2(inbound_head, head);
259 	BUS_SPACE_WRT4_MV0(inbound_doorbell, MVIOP_MU_INBOUND_INT_POSTQUEUE);
260 }
261 
262 static void hptiop_post_msg_itl(struct hpt_iop_hba *hba, u_int32_t msg)
263 {
264 	BUS_SPACE_WRT4_ITL(inbound_msgaddr0, msg);
265 	BUS_SPACE_RD4_ITL(outbound_intstatus);
266 }
267 
268 static void hptiop_post_msg_mv(struct hpt_iop_hba *hba, u_int32_t msg)
269 {
270 
271 	BUS_SPACE_WRT4_MV2(inbound_msg, msg);
272 	BUS_SPACE_WRT4_MV0(inbound_doorbell, MVIOP_MU_INBOUND_INT_MSG);
273 
274 	BUS_SPACE_RD4_MV0(outbound_intmask);
275 }
276 
277 static void hptiop_post_msg_mvfrey(struct hpt_iop_hba *hba, u_int32_t msg)
278 {
279 	BUS_SPACE_WRT4_MVFREY2(f0_to_cpu_msg_a, msg);
280 	BUS_SPACE_RD4_MVFREY2(f0_to_cpu_msg_a);
281 }
282 
283 static int hptiop_wait_ready_itl(struct hpt_iop_hba * hba, u_int32_t millisec)
284 {
285 	u_int32_t req=0;
286 	int i;
287 
288 	for (i = 0; i < millisec; i++) {
289 		req = BUS_SPACE_RD4_ITL(inbound_queue);
290 		if (req != IOPMU_QUEUE_EMPTY)
291 			break;
292 		DELAY(1000);
293 	}
294 
295 	if (req!=IOPMU_QUEUE_EMPTY) {
296 		BUS_SPACE_WRT4_ITL(outbound_queue, req);
297 		BUS_SPACE_RD4_ITL(outbound_intstatus);
298 		return 0;
299 	}
300 
301 	return -1;
302 }
303 
304 static int hptiop_wait_ready_mv(struct hpt_iop_hba * hba, u_int32_t millisec)
305 {
306 	if (hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_NOP, millisec))
307 		return -1;
308 
309 	return 0;
310 }
311 
312 static int hptiop_wait_ready_mvfrey(struct hpt_iop_hba * hba,
313 							u_int32_t millisec)
314 {
315 	if (hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_NOP, millisec))
316 		return -1;
317 
318 	return 0;
319 }
320 
321 static void hptiop_request_callback_itl(struct hpt_iop_hba * hba,
322 							u_int32_t index)
323 {
324 	struct hpt_iop_srb *srb;
325 	struct hpt_iop_request_scsi_command *req=NULL;
326 	union ccb *ccb;
327 	u_int8_t *cdb;
328 	u_int32_t result, temp, dxfer;
329 	u_int64_t temp64;
330 
331 	if (index & IOPMU_QUEUE_MASK_HOST_BITS) { /*host req*/
332 		if (hba->firmware_version > 0x01020000 ||
333 			hba->interface_version > 0x01020000) {
334 			srb = hba->srb[index & ~(u_int32_t)
335 				(IOPMU_QUEUE_ADDR_HOST_BIT
336 				| IOPMU_QUEUE_REQUEST_RESULT_BIT)];
337 			req = (struct hpt_iop_request_scsi_command *)srb;
338 			if (index & IOPMU_QUEUE_REQUEST_RESULT_BIT)
339 				result = IOP_RESULT_SUCCESS;
340 			else
341 				result = req->header.result;
342 		} else {
343 			srb = hba->srb[index &
344 				~(u_int32_t)IOPMU_QUEUE_ADDR_HOST_BIT];
345 			req = (struct hpt_iop_request_scsi_command *)srb;
346 			result = req->header.result;
347 		}
348 		dxfer = req->dataxfer_length;
349 		goto srb_complete;
350 	}
351 
352 	/*iop req*/
353 	temp = bus_space_read_4(hba->bar0t, hba->bar0h, index +
354 		offsetof(struct hpt_iop_request_header, type));
355 	result = bus_space_read_4(hba->bar0t, hba->bar0h, index +
356 		offsetof(struct hpt_iop_request_header, result));
357 	switch(temp) {
358 	case IOP_REQUEST_TYPE_IOCTL_COMMAND:
359 	{
360 		temp64 = 0;
361 		bus_space_write_region_4(hba->bar0t, hba->bar0h, index +
362 			offsetof(struct hpt_iop_request_header, context),
363 			(u_int32_t *)&temp64, 2);
364 		wakeup((void *)((unsigned long)hba->u.itl.mu + index));
365 		break;
366 	}
367 
368 	case IOP_REQUEST_TYPE_SCSI_COMMAND:
369 		bus_space_read_region_4(hba->bar0t, hba->bar0h, index +
370 			offsetof(struct hpt_iop_request_header, context),
371 			(u_int32_t *)&temp64, 2);
372 		srb = (struct hpt_iop_srb *)(unsigned long)temp64;
373 		dxfer = bus_space_read_4(hba->bar0t, hba->bar0h,
374 				index + offsetof(struct hpt_iop_request_scsi_command,
375 				dataxfer_length));
376 srb_complete:
377 		ccb = (union ccb *)srb->ccb;
378 		if (ccb->ccb_h.flags & CAM_CDB_POINTER)
379 			cdb = ccb->csio.cdb_io.cdb_ptr;
380 		else
381 			cdb = ccb->csio.cdb_io.cdb_bytes;
382 
383 		if (cdb[0] == SYNCHRONIZE_CACHE) { /* ??? */
384 			ccb->ccb_h.status = CAM_REQ_CMP;
385 			goto scsi_done;
386 		}
387 
388 		switch (result) {
389 		case IOP_RESULT_SUCCESS:
390 			switch (ccb->ccb_h.flags & CAM_DIR_MASK) {
391 			case CAM_DIR_IN:
392 				bus_dmamap_sync(hba->io_dmat,
393 					srb->dma_map, BUS_DMASYNC_POSTREAD);
394 				bus_dmamap_unload(hba->io_dmat, srb->dma_map);
395 				break;
396 			case CAM_DIR_OUT:
397 				bus_dmamap_sync(hba->io_dmat,
398 					srb->dma_map, BUS_DMASYNC_POSTWRITE);
399 				bus_dmamap_unload(hba->io_dmat, srb->dma_map);
400 				break;
401 			}
402 
403 			ccb->ccb_h.status = CAM_REQ_CMP;
404 			break;
405 
406 		case IOP_RESULT_BAD_TARGET:
407 			ccb->ccb_h.status = CAM_DEV_NOT_THERE;
408 			break;
409 		case IOP_RESULT_BUSY:
410 			ccb->ccb_h.status = CAM_BUSY;
411 			break;
412 		case IOP_RESULT_INVALID_REQUEST:
413 			ccb->ccb_h.status = CAM_REQ_INVALID;
414 			break;
415 		case IOP_RESULT_FAIL:
416 			ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
417 			break;
418 		case IOP_RESULT_RESET:
419 			ccb->ccb_h.status = CAM_BUSY;
420 			break;
421 		case IOP_RESULT_CHECK_CONDITION:
422 			memset(&ccb->csio.sense_data, 0,
423 			    sizeof(ccb->csio.sense_data));
424 			if (dxfer < ccb->csio.sense_len)
425 				ccb->csio.sense_resid = ccb->csio.sense_len -
426 				    dxfer;
427 			else
428 				ccb->csio.sense_resid = 0;
429 			if (srb->srb_flag & HPT_SRB_FLAG_HIGH_MEM_ACESS) {/*iop*/
430 				bus_space_read_region_1(hba->bar0t, hba->bar0h,
431 					index + offsetof(struct hpt_iop_request_scsi_command,
432 					sg_list), (u_int8_t *)&ccb->csio.sense_data,
433 					MIN(dxfer, sizeof(ccb->csio.sense_data)));
434 			} else {
435 				memcpy(&ccb->csio.sense_data, &req->sg_list,
436 					MIN(dxfer, sizeof(ccb->csio.sense_data)));
437 			}
438 			ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
439 			ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
440 			ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
441 			break;
442 		default:
443 			ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
444 			break;
445 		}
446 scsi_done:
447 		if (srb->srb_flag & HPT_SRB_FLAG_HIGH_MEM_ACESS)
448 			BUS_SPACE_WRT4_ITL(outbound_queue, index);
449 
450 		ccb->csio.resid = ccb->csio.dxfer_len - dxfer;
451 
452 		hptiop_free_srb(hba, srb);
453 		xpt_done(ccb);
454 		break;
455 	}
456 }
457 
458 static void hptiop_drain_outbound_queue_itl(struct hpt_iop_hba *hba)
459 {
460 	u_int32_t req, temp;
461 
462 	while ((req = BUS_SPACE_RD4_ITL(outbound_queue)) !=IOPMU_QUEUE_EMPTY) {
463 		if (req & IOPMU_QUEUE_MASK_HOST_BITS)
464 			hptiop_request_callback_itl(hba, req);
465 		else {
466 			temp = bus_space_read_4(hba->bar0t,
467 					hba->bar0h,req +
468 					offsetof(struct hpt_iop_request_header,
469 						flags));
470 			if (temp & IOP_REQUEST_FLAG_SYNC_REQUEST) {
471 				u_int64_t temp64;
472 				bus_space_read_region_4(hba->bar0t,
473 					hba->bar0h,req +
474 					offsetof(struct hpt_iop_request_header,
475 						context),
476 					(u_int32_t *)&temp64, 2);
477 				if (temp64) {
478 					hptiop_request_callback_itl(hba, req);
479 				} else {
480 					temp64 = 1;
481 					bus_space_write_region_4(hba->bar0t,
482 						hba->bar0h,req +
483 						offsetof(struct hpt_iop_request_header,
484 							context),
485 						(u_int32_t *)&temp64, 2);
486 				}
487 			} else
488 				hptiop_request_callback_itl(hba, req);
489 		}
490 	}
491 }
492 
493 static int hptiop_intr_itl(struct hpt_iop_hba * hba)
494 {
495 	u_int32_t status;
496 	int ret = 0;
497 
498 	status = BUS_SPACE_RD4_ITL(outbound_intstatus);
499 
500 	if (status & IOPMU_OUTBOUND_INT_MSG0) {
501 		u_int32_t msg = BUS_SPACE_RD4_ITL(outbound_msgaddr0);
502 		KdPrint(("hptiop: received outbound msg %x\n", msg));
503 		BUS_SPACE_WRT4_ITL(outbound_intstatus, IOPMU_OUTBOUND_INT_MSG0);
504 		hptiop_os_message_callback(hba, msg);
505 		ret = 1;
506 	}
507 
508 	if (status & IOPMU_OUTBOUND_INT_POSTQUEUE) {
509 		hptiop_drain_outbound_queue_itl(hba);
510 		ret = 1;
511 	}
512 
513 	return ret;
514 }
515 
516 static void hptiop_request_callback_mv(struct hpt_iop_hba * hba,
517 							u_int64_t _tag)
518 {
519 	u_int32_t context = (u_int32_t)_tag;
520 
521 	if (context & MVIOP_CMD_TYPE_SCSI) {
522 		struct hpt_iop_srb *srb;
523 		struct hpt_iop_request_scsi_command *req;
524 		union ccb *ccb;
525 		u_int8_t *cdb;
526 
527 		srb = hba->srb[context >> MVIOP_REQUEST_NUMBER_START_BIT];
528 		req = (struct hpt_iop_request_scsi_command *)srb;
529 		ccb = (union ccb *)srb->ccb;
530 		if (ccb->ccb_h.flags & CAM_CDB_POINTER)
531 			cdb = ccb->csio.cdb_io.cdb_ptr;
532 		else
533 			cdb = ccb->csio.cdb_io.cdb_bytes;
534 
535 		if (cdb[0] == SYNCHRONIZE_CACHE) { /* ??? */
536 			ccb->ccb_h.status = CAM_REQ_CMP;
537 			goto scsi_done;
538 		}
539 		if (context & MVIOP_MU_QUEUE_REQUEST_RESULT_BIT)
540 			req->header.result = IOP_RESULT_SUCCESS;
541 
542 		switch (req->header.result) {
543 		case IOP_RESULT_SUCCESS:
544 			switch (ccb->ccb_h.flags & CAM_DIR_MASK) {
545 			case CAM_DIR_IN:
546 				bus_dmamap_sync(hba->io_dmat,
547 					srb->dma_map, BUS_DMASYNC_POSTREAD);
548 				bus_dmamap_unload(hba->io_dmat, srb->dma_map);
549 				break;
550 			case CAM_DIR_OUT:
551 				bus_dmamap_sync(hba->io_dmat,
552 					srb->dma_map, BUS_DMASYNC_POSTWRITE);
553 				bus_dmamap_unload(hba->io_dmat, srb->dma_map);
554 				break;
555 			}
556 			ccb->ccb_h.status = CAM_REQ_CMP;
557 			break;
558 		case IOP_RESULT_BAD_TARGET:
559 			ccb->ccb_h.status = CAM_DEV_NOT_THERE;
560 			break;
561 		case IOP_RESULT_BUSY:
562 			ccb->ccb_h.status = CAM_BUSY;
563 			break;
564 		case IOP_RESULT_INVALID_REQUEST:
565 			ccb->ccb_h.status = CAM_REQ_INVALID;
566 			break;
567 		case IOP_RESULT_FAIL:
568 			ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
569 			break;
570 		case IOP_RESULT_RESET:
571 			ccb->ccb_h.status = CAM_BUSY;
572 			break;
573 		case IOP_RESULT_CHECK_CONDITION:
574 			memset(&ccb->csio.sense_data, 0,
575 			    sizeof(ccb->csio.sense_data));
576 			if (req->dataxfer_length < ccb->csio.sense_len)
577 				ccb->csio.sense_resid = ccb->csio.sense_len -
578 				    req->dataxfer_length;
579 			else
580 				ccb->csio.sense_resid = 0;
581 			memcpy(&ccb->csio.sense_data, &req->sg_list,
582 				MIN(req->dataxfer_length, sizeof(ccb->csio.sense_data)));
583 			ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
584 			ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
585 			ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
586 			break;
587 		default:
588 			ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
589 			break;
590 		}
591 scsi_done:
592 		ccb->csio.resid = ccb->csio.dxfer_len - req->dataxfer_length;
593 
594 		hptiop_free_srb(hba, srb);
595 		xpt_done(ccb);
596 	} else if (context & MVIOP_CMD_TYPE_IOCTL) {
597 		struct hpt_iop_request_ioctl_command *req = hba->ctlcfg_ptr;
598 		if (context & MVIOP_MU_QUEUE_REQUEST_RESULT_BIT)
599 			hba->config_done = 1;
600 		else
601 			hba->config_done = -1;
602 		wakeup(req);
603 	} else if (context &
604 			(MVIOP_CMD_TYPE_SET_CONFIG |
605 				MVIOP_CMD_TYPE_GET_CONFIG))
606 		hba->config_done = 1;
607 	else {
608 		device_printf(hba->pcidev, "wrong callback type\n");
609 	}
610 }
611 
612 static void hptiop_request_callback_mvfrey(struct hpt_iop_hba * hba,
613 				u_int32_t _tag)
614 {
615 	u_int32_t req_type = _tag & 0xf;
616 
617 	struct hpt_iop_srb *srb;
618 	struct hpt_iop_request_scsi_command *req;
619 	union ccb *ccb;
620 	u_int8_t *cdb;
621 
622 	switch (req_type) {
623 	case IOP_REQUEST_TYPE_GET_CONFIG:
624 	case IOP_REQUEST_TYPE_SET_CONFIG:
625 		hba->config_done = 1;
626 		break;
627 
628 	case IOP_REQUEST_TYPE_SCSI_COMMAND:
629 		srb = hba->srb[(_tag >> 4) & 0xff];
630 		req = (struct hpt_iop_request_scsi_command *)srb;
631 
632 		ccb = (union ccb *)srb->ccb;
633 
634 		callout_stop(&srb->timeout);
635 
636 		if (ccb->ccb_h.flags & CAM_CDB_POINTER)
637 			cdb = ccb->csio.cdb_io.cdb_ptr;
638 		else
639 			cdb = ccb->csio.cdb_io.cdb_bytes;
640 
641 		if (cdb[0] == SYNCHRONIZE_CACHE) { /* ??? */
642 			ccb->ccb_h.status = CAM_REQ_CMP;
643 			goto scsi_done;
644 		}
645 
646 		if (_tag & MVFREYIOPMU_QUEUE_REQUEST_RESULT_BIT)
647 			req->header.result = IOP_RESULT_SUCCESS;
648 
649 		switch (req->header.result) {
650 		case IOP_RESULT_SUCCESS:
651 			switch (ccb->ccb_h.flags & CAM_DIR_MASK) {
652 			case CAM_DIR_IN:
653 				bus_dmamap_sync(hba->io_dmat,
654 						srb->dma_map, BUS_DMASYNC_POSTREAD);
655 				bus_dmamap_unload(hba->io_dmat, srb->dma_map);
656 				break;
657 			case CAM_DIR_OUT:
658 				bus_dmamap_sync(hba->io_dmat,
659 						srb->dma_map, BUS_DMASYNC_POSTWRITE);
660 				bus_dmamap_unload(hba->io_dmat, srb->dma_map);
661 				break;
662 			}
663 			ccb->ccb_h.status = CAM_REQ_CMP;
664 			break;
665 		case IOP_RESULT_BAD_TARGET:
666 			ccb->ccb_h.status = CAM_DEV_NOT_THERE;
667 			break;
668 		case IOP_RESULT_BUSY:
669 			ccb->ccb_h.status = CAM_BUSY;
670 			break;
671 		case IOP_RESULT_INVALID_REQUEST:
672 			ccb->ccb_h.status = CAM_REQ_INVALID;
673 			break;
674 		case IOP_RESULT_FAIL:
675 			ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
676 			break;
677 		case IOP_RESULT_RESET:
678 			ccb->ccb_h.status = CAM_BUSY;
679 			break;
680 		case IOP_RESULT_CHECK_CONDITION:
681 			memset(&ccb->csio.sense_data, 0,
682 			       sizeof(ccb->csio.sense_data));
683 			if (req->dataxfer_length < ccb->csio.sense_len)
684 				ccb->csio.sense_resid = ccb->csio.sense_len -
685 				req->dataxfer_length;
686 			else
687 				ccb->csio.sense_resid = 0;
688 			memcpy(&ccb->csio.sense_data, &req->sg_list,
689 			       MIN(req->dataxfer_length, sizeof(ccb->csio.sense_data)));
690 			ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
691 			ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
692 			ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
693 			break;
694 		default:
695 			ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
696 			break;
697 		}
698 scsi_done:
699 		ccb->csio.resid = ccb->csio.dxfer_len - req->dataxfer_length;
700 
701 		hptiop_free_srb(hba, srb);
702 		xpt_done(ccb);
703 		break;
704 	case IOP_REQUEST_TYPE_IOCTL_COMMAND:
705 		if (_tag & MVFREYIOPMU_QUEUE_REQUEST_RESULT_BIT)
706 			hba->config_done = 1;
707 		else
708 			hba->config_done = -1;
709 		wakeup((struct hpt_iop_request_ioctl_command *)hba->ctlcfg_ptr);
710 		break;
711 	default:
712 		device_printf(hba->pcidev, "wrong callback type\n");
713 		break;
714 	}
715 }
716 
717 static void hptiop_drain_outbound_queue_mv(struct hpt_iop_hba * hba)
718 {
719 	u_int64_t req;
720 
721 	while ((req = hptiop_mv_outbound_read(hba))) {
722 		if (req & MVIOP_MU_QUEUE_ADDR_HOST_BIT) {
723 			if (req & MVIOP_MU_QUEUE_REQUEST_RETURN_CONTEXT) {
724 				hptiop_request_callback_mv(hba, req);
725 			}
726 	    	}
727 	}
728 }
729 
730 static int hptiop_intr_mv(struct hpt_iop_hba * hba)
731 {
732 	u_int32_t status;
733 	int ret = 0;
734 
735 	status = BUS_SPACE_RD4_MV0(outbound_doorbell);
736 
737 	if (status)
738 		BUS_SPACE_WRT4_MV0(outbound_doorbell, ~status);
739 
740 	if (status & MVIOP_MU_OUTBOUND_INT_MSG) {
741 		u_int32_t msg = BUS_SPACE_RD4_MV2(outbound_msg);
742 		KdPrint(("hptiop: received outbound msg %x\n", msg));
743 		hptiop_os_message_callback(hba, msg);
744 		ret = 1;
745 	}
746 
747 	if (status & MVIOP_MU_OUTBOUND_INT_POSTQUEUE) {
748 		hptiop_drain_outbound_queue_mv(hba);
749 		ret = 1;
750 	}
751 
752 	return ret;
753 }
754 
755 static int hptiop_intr_mvfrey(struct hpt_iop_hba * hba)
756 {
757 	u_int32_t status, _tag, cptr;
758 	int ret = 0;
759 
760 	if (hba->initialized) {
761 		BUS_SPACE_WRT4_MVFREY2(pcie_f0_int_enable, 0);
762 	}
763 
764 	status = BUS_SPACE_RD4_MVFREY2(f0_doorbell);
765 	if (status) {
766 		BUS_SPACE_WRT4_MVFREY2(f0_doorbell, status);
767 		if (status & CPU_TO_F0_DRBL_MSG_A_BIT) {
768 			u_int32_t msg = BUS_SPACE_RD4_MVFREY2(cpu_to_f0_msg_a);
769 			hptiop_os_message_callback(hba, msg);
770 		}
771 		ret = 1;
772 	}
773 
774 	status = BUS_SPACE_RD4_MVFREY2(isr_cause);
775 	if (status) {
776 		BUS_SPACE_WRT4_MVFREY2(isr_cause, status);
777 		do {
778 			cptr = *hba->u.mvfrey.outlist_cptr & 0xff;
779 			while (hba->u.mvfrey.outlist_rptr != cptr) {
780 				hba->u.mvfrey.outlist_rptr++;
781 				if (hba->u.mvfrey.outlist_rptr == hba->u.mvfrey.list_count) {
782 					hba->u.mvfrey.outlist_rptr = 0;
783 				}
784 
785 				_tag = hba->u.mvfrey.outlist[hba->u.mvfrey.outlist_rptr].val;
786 				hptiop_request_callback_mvfrey(hba, _tag);
787 				ret = 2;
788 			}
789 		} while (cptr != (*hba->u.mvfrey.outlist_cptr & 0xff));
790 	}
791 
792 	if (hba->initialized) {
793 		BUS_SPACE_WRT4_MVFREY2(pcie_f0_int_enable, 0x1010);
794 	}
795 
796 	return ret;
797 }
798 
799 static int hptiop_send_sync_request_itl(struct hpt_iop_hba * hba,
800 					u_int32_t req32, u_int32_t millisec)
801 {
802 	u_int32_t i;
803 	u_int64_t temp64;
804 
805 	BUS_SPACE_WRT4_ITL(inbound_queue, req32);
806 	BUS_SPACE_RD4_ITL(outbound_intstatus);
807 
808 	for (i = 0; i < millisec; i++) {
809 		hptiop_intr_itl(hba);
810 		bus_space_read_region_4(hba->bar0t, hba->bar0h, req32 +
811 			offsetof(struct hpt_iop_request_header, context),
812 			(u_int32_t *)&temp64, 2);
813 		if (temp64)
814 			return 0;
815 		DELAY(1000);
816 	}
817 
818 	return -1;
819 }
820 
821 static int hptiop_send_sync_request_mv(struct hpt_iop_hba *hba,
822 					void *req, u_int32_t millisec)
823 {
824 	u_int32_t i;
825 	u_int64_t phy_addr;
826 	hba->config_done = 0;
827 
828 	phy_addr = hba->ctlcfgcmd_phy |
829 			(u_int64_t)MVIOP_MU_QUEUE_ADDR_HOST_BIT;
830 	((struct hpt_iop_request_get_config *)req)->header.flags |=
831 		IOP_REQUEST_FLAG_SYNC_REQUEST |
832 		IOP_REQUEST_FLAG_OUTPUT_CONTEXT;
833 	hptiop_mv_inbound_write(phy_addr, hba);
834 	BUS_SPACE_RD4_MV0(outbound_intmask);
835 
836 	for (i = 0; i < millisec; i++) {
837 		hptiop_intr_mv(hba);
838 		if (hba->config_done)
839 			return 0;
840 		DELAY(1000);
841 	}
842 	return -1;
843 }
844 
845 static int hptiop_send_sync_request_mvfrey(struct hpt_iop_hba *hba,
846 					void *req, u_int32_t millisec)
847 {
848 	u_int32_t i, index;
849 	u_int64_t phy_addr;
850 	struct hpt_iop_request_header *reqhdr =
851 										(struct hpt_iop_request_header *)req;
852 
853 	hba->config_done = 0;
854 
855 	phy_addr = hba->ctlcfgcmd_phy;
856 	reqhdr->flags = IOP_REQUEST_FLAG_SYNC_REQUEST
857 					| IOP_REQUEST_FLAG_OUTPUT_CONTEXT
858 					| IOP_REQUEST_FLAG_ADDR_BITS
859 					| ((phy_addr >> 16) & 0xffff0000);
860 	reqhdr->context = ((phy_addr & 0xffffffff) << 32 )
861 					| IOPMU_QUEUE_ADDR_HOST_BIT | reqhdr->type;
862 
863 	hba->u.mvfrey.inlist_wptr++;
864 	index = hba->u.mvfrey.inlist_wptr & 0x3fff;
865 
866 	if (index == hba->u.mvfrey.list_count) {
867 		index = 0;
868 		hba->u.mvfrey.inlist_wptr &= ~0x3fff;
869 		hba->u.mvfrey.inlist_wptr ^= CL_POINTER_TOGGLE;
870 	}
871 
872 	hba->u.mvfrey.inlist[index].addr = phy_addr;
873 	hba->u.mvfrey.inlist[index].intrfc_len = (reqhdr->size + 3) / 4;
874 
875 	BUS_SPACE_WRT4_MVFREY2(inbound_write_ptr, hba->u.mvfrey.inlist_wptr);
876 	BUS_SPACE_RD4_MVFREY2(inbound_write_ptr);
877 
878 	for (i = 0; i < millisec; i++) {
879 		hptiop_intr_mvfrey(hba);
880 		if (hba->config_done)
881 			return 0;
882 		DELAY(1000);
883 	}
884 	return -1;
885 }
886 
887 static int hptiop_send_sync_msg(struct hpt_iop_hba *hba,
888 					u_int32_t msg, u_int32_t millisec)
889 {
890 	u_int32_t i;
891 
892 	hba->msg_done = 0;
893 	hba->ops->post_msg(hba, msg);
894 
895 	for (i=0; i<millisec; i++) {
896 		hba->ops->iop_intr(hba);
897 		if (hba->msg_done)
898 			break;
899 		DELAY(1000);
900 	}
901 
902 	return hba->msg_done? 0 : -1;
903 }
904 
905 static int hptiop_get_config_itl(struct hpt_iop_hba * hba,
906 				struct hpt_iop_request_get_config * config)
907 {
908 	u_int32_t req32;
909 
910 	config->header.size = sizeof(struct hpt_iop_request_get_config);
911 	config->header.type = IOP_REQUEST_TYPE_GET_CONFIG;
912 	config->header.flags = IOP_REQUEST_FLAG_SYNC_REQUEST;
913 	config->header.result = IOP_RESULT_PENDING;
914 	config->header.context = 0;
915 
916 	req32 = BUS_SPACE_RD4_ITL(inbound_queue);
917 	if (req32 == IOPMU_QUEUE_EMPTY)
918 		return -1;
919 
920 	bus_space_write_region_4(hba->bar0t, hba->bar0h,
921 			req32, (u_int32_t *)config,
922 			sizeof(struct hpt_iop_request_header) >> 2);
923 
924 	if (hptiop_send_sync_request_itl(hba, req32, 20000)) {
925 		KdPrint(("hptiop: get config send cmd failed"));
926 		return -1;
927 	}
928 
929 	bus_space_read_region_4(hba->bar0t, hba->bar0h,
930 			req32, (u_int32_t *)config,
931 			sizeof(struct hpt_iop_request_get_config) >> 2);
932 
933 	BUS_SPACE_WRT4_ITL(outbound_queue, req32);
934 
935 	return 0;
936 }
937 
938 static int hptiop_get_config_mv(struct hpt_iop_hba * hba,
939 				struct hpt_iop_request_get_config * config)
940 {
941 	struct hpt_iop_request_get_config *req;
942 
943 	if (!(req = hba->ctlcfg_ptr))
944 		return -1;
945 
946 	req->header.flags = 0;
947 	req->header.type = IOP_REQUEST_TYPE_GET_CONFIG;
948 	req->header.size = sizeof(struct hpt_iop_request_get_config);
949 	req->header.result = IOP_RESULT_PENDING;
950 	req->header.context = MVIOP_CMD_TYPE_GET_CONFIG;
951 
952 	if (hptiop_send_sync_request_mv(hba, req, 20000)) {
953 		KdPrint(("hptiop: get config send cmd failed"));
954 		return -1;
955 	}
956 
957 	*config = *req;
958 	return 0;
959 }
960 
961 static int hptiop_get_config_mvfrey(struct hpt_iop_hba * hba,
962 				struct hpt_iop_request_get_config * config)
963 {
964 	struct hpt_iop_request_get_config *info = hba->u.mvfrey.config;
965 
966 	if (info->header.size != sizeof(struct hpt_iop_request_get_config) ||
967 	    info->header.type != IOP_REQUEST_TYPE_GET_CONFIG) {
968 		KdPrint(("hptiop: header size %x/%x type %x/%x",
969 			 info->header.size, (int)sizeof(struct hpt_iop_request_get_config),
970 			 info->header.type, IOP_REQUEST_TYPE_GET_CONFIG));
971 		return -1;
972 	}
973 
974 	config->interface_version = info->interface_version;
975 	config->firmware_version = info->firmware_version;
976 	config->max_requests = info->max_requests;
977 	config->request_size = info->request_size;
978 	config->max_sg_count = info->max_sg_count;
979 	config->data_transfer_length = info->data_transfer_length;
980 	config->alignment_mask = info->alignment_mask;
981 	config->max_devices = info->max_devices;
982 	config->sdram_size = info->sdram_size;
983 
984 	KdPrint(("hptiop: maxreq %x reqsz %x datalen %x maxdev %x sdram %x",
985 		 config->max_requests, config->request_size,
986 		 config->data_transfer_length, config->max_devices,
987 		 config->sdram_size));
988 
989 	return 0;
990 }
991 
992 static int hptiop_set_config_itl(struct hpt_iop_hba *hba,
993 				struct hpt_iop_request_set_config *config)
994 {
995 	u_int32_t req32;
996 
997 	req32 = BUS_SPACE_RD4_ITL(inbound_queue);
998 
999 	if (req32 == IOPMU_QUEUE_EMPTY)
1000 		return -1;
1001 
1002 	config->header.size = sizeof(struct hpt_iop_request_set_config);
1003 	config->header.type = IOP_REQUEST_TYPE_SET_CONFIG;
1004 	config->header.flags = IOP_REQUEST_FLAG_SYNC_REQUEST;
1005 	config->header.result = IOP_RESULT_PENDING;
1006 	config->header.context = 0;
1007 
1008 	bus_space_write_region_4(hba->bar0t, hba->bar0h, req32,
1009 		(u_int32_t *)config,
1010 		sizeof(struct hpt_iop_request_set_config) >> 2);
1011 
1012 	if (hptiop_send_sync_request_itl(hba, req32, 20000)) {
1013 		KdPrint(("hptiop: set config send cmd failed"));
1014 		return -1;
1015 	}
1016 
1017 	BUS_SPACE_WRT4_ITL(outbound_queue, req32);
1018 
1019 	return 0;
1020 }
1021 
1022 static int hptiop_set_config_mv(struct hpt_iop_hba *hba,
1023 				struct hpt_iop_request_set_config *config)
1024 {
1025 	struct hpt_iop_request_set_config *req;
1026 
1027 	if (!(req = hba->ctlcfg_ptr))
1028 		return -1;
1029 
1030 	memcpy((u_int8_t *)req + sizeof(struct hpt_iop_request_header),
1031 		(u_int8_t *)config + sizeof(struct hpt_iop_request_header),
1032 		sizeof(struct hpt_iop_request_set_config) -
1033 			sizeof(struct hpt_iop_request_header));
1034 
1035 	req->header.flags = 0;
1036 	req->header.type = IOP_REQUEST_TYPE_SET_CONFIG;
1037 	req->header.size = sizeof(struct hpt_iop_request_set_config);
1038 	req->header.result = IOP_RESULT_PENDING;
1039 	req->header.context = MVIOP_CMD_TYPE_SET_CONFIG;
1040 
1041 	if (hptiop_send_sync_request_mv(hba, req, 20000)) {
1042 		KdPrint(("hptiop: set config send cmd failed"));
1043 		return -1;
1044 	}
1045 
1046 	return 0;
1047 }
1048 
1049 static int hptiop_set_config_mvfrey(struct hpt_iop_hba *hba,
1050 				struct hpt_iop_request_set_config *config)
1051 {
1052 	struct hpt_iop_request_set_config *req;
1053 
1054 	if (!(req = hba->ctlcfg_ptr))
1055 		return -1;
1056 
1057 	memcpy((u_int8_t *)req + sizeof(struct hpt_iop_request_header),
1058 		(u_int8_t *)config + sizeof(struct hpt_iop_request_header),
1059 		sizeof(struct hpt_iop_request_set_config) -
1060 			sizeof(struct hpt_iop_request_header));
1061 
1062 	req->header.type = IOP_REQUEST_TYPE_SET_CONFIG;
1063 	req->header.size = sizeof(struct hpt_iop_request_set_config);
1064 	req->header.result = IOP_RESULT_PENDING;
1065 
1066 	if (hptiop_send_sync_request_mvfrey(hba, req, 20000)) {
1067 		KdPrint(("hptiop: set config send cmd failed"));
1068 		return -1;
1069 	}
1070 
1071 	return 0;
1072 }
1073 
1074 static int hptiop_post_ioctl_command_itl(struct hpt_iop_hba *hba,
1075 				u_int32_t req32,
1076 				struct hpt_iop_ioctl_param *pParams)
1077 {
1078 	u_int64_t temp64;
1079 	struct hpt_iop_request_ioctl_command req;
1080 
1081 	if ((((pParams->nInBufferSize + 3) & ~3) + pParams->nOutBufferSize) >
1082 			(hba->max_request_size -
1083 			offsetof(struct hpt_iop_request_ioctl_command, buf))) {
1084 		device_printf(hba->pcidev, "request size beyond max value");
1085 		return -1;
1086 	}
1087 
1088 	req.header.size = offsetof(struct hpt_iop_request_ioctl_command, buf)
1089 		+ pParams->nInBufferSize;
1090 	req.header.type = IOP_REQUEST_TYPE_IOCTL_COMMAND;
1091 	req.header.flags = IOP_REQUEST_FLAG_SYNC_REQUEST;
1092 	req.header.result = IOP_RESULT_PENDING;
1093 	req.header.context = req32 + (u_int64_t)(unsigned long)hba->u.itl.mu;
1094 	req.ioctl_code = HPT_CTL_CODE_BSD_TO_IOP(pParams->dwIoControlCode);
1095 	req.inbuf_size = pParams->nInBufferSize;
1096 	req.outbuf_size = pParams->nOutBufferSize;
1097 	req.bytes_returned = 0;
1098 
1099 	bus_space_write_region_4(hba->bar0t, hba->bar0h, req32, (u_int32_t *)&req,
1100 		offsetof(struct hpt_iop_request_ioctl_command, buf)>>2);
1101 
1102 	hptiop_lock_adapter(hba);
1103 
1104 	BUS_SPACE_WRT4_ITL(inbound_queue, req32);
1105 	BUS_SPACE_RD4_ITL(outbound_intstatus);
1106 
1107 	bus_space_read_region_4(hba->bar0t, hba->bar0h, req32 +
1108 		offsetof(struct hpt_iop_request_ioctl_command, header.context),
1109 		(u_int32_t *)&temp64, 2);
1110 	while (temp64) {
1111 		if (hptiop_sleep(hba, (void *)((unsigned long)hba->u.itl.mu + req32),
1112 				PPAUSE, "hptctl", HPT_OSM_TIMEOUT)==0)
1113 			break;
1114 		hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_RESET, 60000);
1115 		bus_space_read_region_4(hba->bar0t, hba->bar0h,req32 +
1116 			offsetof(struct hpt_iop_request_ioctl_command,
1117 				header.context),
1118 			(u_int32_t *)&temp64, 2);
1119 	}
1120 
1121 	hptiop_unlock_adapter(hba);
1122 	return 0;
1123 }
1124 
1125 static int hptiop_bus_space_copyin(struct hpt_iop_hba *hba, u_int32_t bus,
1126 									void *user, int size)
1127 {
1128 	unsigned char byte;
1129 	int i;
1130 
1131 	for (i=0; i<size; i++) {
1132 		if (copyin((u_int8_t *)user + i, &byte, 1))
1133 			return -1;
1134 		bus_space_write_1(hba->bar0t, hba->bar0h, bus + i, byte);
1135 	}
1136 
1137 	return 0;
1138 }
1139 
1140 static int hptiop_bus_space_copyout(struct hpt_iop_hba *hba, u_int32_t bus,
1141 									void *user, int size)
1142 {
1143 	unsigned char byte;
1144 	int i;
1145 
1146 	for (i=0; i<size; i++) {
1147 		byte = bus_space_read_1(hba->bar0t, hba->bar0h, bus + i);
1148 		if (copyout(&byte, (u_int8_t *)user + i, 1))
1149 			return -1;
1150 	}
1151 
1152 	return 0;
1153 }
1154 
1155 static int hptiop_do_ioctl_itl(struct hpt_iop_hba *hba,
1156 				struct hpt_iop_ioctl_param * pParams)
1157 {
1158 	u_int32_t req32;
1159 	u_int32_t result;
1160 
1161 	if ((pParams->Magic != HPT_IOCTL_MAGIC) &&
1162 		(pParams->Magic != HPT_IOCTL_MAGIC32))
1163 		return EFAULT;
1164 
1165 	req32 = BUS_SPACE_RD4_ITL(inbound_queue);
1166 	if (req32 == IOPMU_QUEUE_EMPTY)
1167 		return EFAULT;
1168 
1169 	if (pParams->nInBufferSize)
1170 		if (hptiop_bus_space_copyin(hba, req32 +
1171 			offsetof(struct hpt_iop_request_ioctl_command, buf),
1172 			(void *)pParams->lpInBuffer, pParams->nInBufferSize))
1173 			goto invalid;
1174 
1175 	if (hptiop_post_ioctl_command_itl(hba, req32, pParams))
1176 		goto invalid;
1177 
1178 	result = bus_space_read_4(hba->bar0t, hba->bar0h, req32 +
1179 			offsetof(struct hpt_iop_request_ioctl_command,
1180 				header.result));
1181 
1182 	if (result == IOP_RESULT_SUCCESS) {
1183 		if (pParams->nOutBufferSize)
1184 			if (hptiop_bus_space_copyout(hba, req32 +
1185 				offsetof(struct hpt_iop_request_ioctl_command, buf) +
1186 					((pParams->nInBufferSize + 3) & ~3),
1187 				(void *)pParams->lpOutBuffer, pParams->nOutBufferSize))
1188 				goto invalid;
1189 
1190 		if (pParams->lpBytesReturned) {
1191 			if (hptiop_bus_space_copyout(hba, req32 +
1192 				offsetof(struct hpt_iop_request_ioctl_command, bytes_returned),
1193 				(void *)pParams->lpBytesReturned, sizeof(unsigned  long)))
1194 				goto invalid;
1195 		}
1196 
1197 		BUS_SPACE_WRT4_ITL(outbound_queue, req32);
1198 
1199 		return 0;
1200 	} else{
1201 invalid:
1202 		BUS_SPACE_WRT4_ITL(outbound_queue, req32);
1203 
1204 		return EFAULT;
1205 	}
1206 }
1207 
1208 static int hptiop_post_ioctl_command_mv(struct hpt_iop_hba *hba,
1209 				struct hpt_iop_request_ioctl_command *req,
1210 				struct hpt_iop_ioctl_param *pParams)
1211 {
1212 	u_int64_t req_phy;
1213 	int size = 0;
1214 
1215 	if ((((pParams->nInBufferSize + 3) & ~3) + pParams->nOutBufferSize) >
1216 			(hba->max_request_size -
1217 			offsetof(struct hpt_iop_request_ioctl_command, buf))) {
1218 		device_printf(hba->pcidev, "request size beyond max value");
1219 		return -1;
1220 	}
1221 
1222 	req->ioctl_code = HPT_CTL_CODE_BSD_TO_IOP(pParams->dwIoControlCode);
1223 	req->inbuf_size = pParams->nInBufferSize;
1224 	req->outbuf_size = pParams->nOutBufferSize;
1225 	req->header.size = offsetof(struct hpt_iop_request_ioctl_command, buf)
1226 					+ pParams->nInBufferSize;
1227 	req->header.context = (u_int64_t)MVIOP_CMD_TYPE_IOCTL;
1228 	req->header.type = IOP_REQUEST_TYPE_IOCTL_COMMAND;
1229 	req->header.result = IOP_RESULT_PENDING;
1230 	req->header.flags = IOP_REQUEST_FLAG_OUTPUT_CONTEXT;
1231 	size = req->header.size >> 8;
1232 	size = imin(3, size);
1233 	req_phy = hba->ctlcfgcmd_phy | MVIOP_MU_QUEUE_ADDR_HOST_BIT | size;
1234 	hptiop_mv_inbound_write(req_phy, hba);
1235 
1236 	BUS_SPACE_RD4_MV0(outbound_intmask);
1237 
1238 	while (hba->config_done == 0) {
1239 		if (hptiop_sleep(hba, req, PPAUSE,
1240 			"hptctl", HPT_OSM_TIMEOUT)==0)
1241 			continue;
1242 		hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_RESET, 60000);
1243 	}
1244 	return 0;
1245 }
1246 
1247 static int hptiop_do_ioctl_mv(struct hpt_iop_hba *hba,
1248 				struct hpt_iop_ioctl_param *pParams)
1249 {
1250 	struct hpt_iop_request_ioctl_command *req;
1251 
1252 	if ((pParams->Magic != HPT_IOCTL_MAGIC) &&
1253 		(pParams->Magic != HPT_IOCTL_MAGIC32))
1254 		return EFAULT;
1255 
1256 	req = (struct hpt_iop_request_ioctl_command *)(hba->ctlcfg_ptr);
1257 	hba->config_done = 0;
1258 	hptiop_lock_adapter(hba);
1259 	if (pParams->nInBufferSize)
1260 		if (copyin((void *)pParams->lpInBuffer,
1261 				req->buf, pParams->nInBufferSize))
1262 			goto invalid;
1263 	if (hptiop_post_ioctl_command_mv(hba, req, pParams))
1264 		goto invalid;
1265 
1266 	if (hba->config_done == 1) {
1267 		if (pParams->nOutBufferSize)
1268 			if (copyout(req->buf +
1269 				((pParams->nInBufferSize + 3) & ~3),
1270 				(void *)pParams->lpOutBuffer,
1271 				pParams->nOutBufferSize))
1272 				goto invalid;
1273 
1274 		if (pParams->lpBytesReturned)
1275 			if (copyout(&req->bytes_returned,
1276 				(void*)pParams->lpBytesReturned,
1277 				sizeof(u_int32_t)))
1278 				goto invalid;
1279 		hptiop_unlock_adapter(hba);
1280 		return 0;
1281 	} else{
1282 invalid:
1283 		hptiop_unlock_adapter(hba);
1284 		return EFAULT;
1285 	}
1286 }
1287 
1288 static int hptiop_post_ioctl_command_mvfrey(struct hpt_iop_hba *hba,
1289 				struct hpt_iop_request_ioctl_command *req,
1290 				struct hpt_iop_ioctl_param *pParams)
1291 {
1292 	u_int64_t phy_addr;
1293 	u_int32_t index;
1294 
1295 	phy_addr = hba->ctlcfgcmd_phy;
1296 
1297 	if ((((pParams->nInBufferSize + 3) & ~3) + pParams->nOutBufferSize) >
1298 			(hba->max_request_size -
1299 			offsetof(struct hpt_iop_request_ioctl_command, buf))) {
1300 		device_printf(hba->pcidev, "request size beyond max value");
1301 		return -1;
1302 	}
1303 
1304 	req->ioctl_code = HPT_CTL_CODE_BSD_TO_IOP(pParams->dwIoControlCode);
1305 	req->inbuf_size = pParams->nInBufferSize;
1306 	req->outbuf_size = pParams->nOutBufferSize;
1307 	req->header.size = offsetof(struct hpt_iop_request_ioctl_command, buf)
1308 					+ pParams->nInBufferSize;
1309 
1310 	req->header.type = IOP_REQUEST_TYPE_IOCTL_COMMAND;
1311 	req->header.result = IOP_RESULT_PENDING;
1312 
1313 	req->header.flags = IOP_REQUEST_FLAG_SYNC_REQUEST
1314 						| IOP_REQUEST_FLAG_OUTPUT_CONTEXT
1315 						| IOP_REQUEST_FLAG_ADDR_BITS
1316 						| ((phy_addr >> 16) & 0xffff0000);
1317 	req->header.context = ((phy_addr & 0xffffffff) << 32 )
1318 						| IOPMU_QUEUE_ADDR_HOST_BIT | req->header.type;
1319 
1320 	hba->u.mvfrey.inlist_wptr++;
1321 	index = hba->u.mvfrey.inlist_wptr & 0x3fff;
1322 
1323 	if (index == hba->u.mvfrey.list_count) {
1324 		index = 0;
1325 		hba->u.mvfrey.inlist_wptr &= ~0x3fff;
1326 		hba->u.mvfrey.inlist_wptr ^= CL_POINTER_TOGGLE;
1327 	}
1328 
1329 	hba->u.mvfrey.inlist[index].addr = phy_addr;
1330 	hba->u.mvfrey.inlist[index].intrfc_len = (req->header.size + 3) / 4;
1331 
1332 	BUS_SPACE_WRT4_MVFREY2(inbound_write_ptr, hba->u.mvfrey.inlist_wptr);
1333 	BUS_SPACE_RD4_MVFREY2(inbound_write_ptr);
1334 
1335 	while (hba->config_done == 0) {
1336 		if (hptiop_sleep(hba, req, PPAUSE,
1337 			"hptctl", HPT_OSM_TIMEOUT)==0)
1338 			continue;
1339 		hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_RESET, 60000);
1340 	}
1341 	return 0;
1342 }
1343 
1344 static int hptiop_do_ioctl_mvfrey(struct hpt_iop_hba *hba,
1345 				struct hpt_iop_ioctl_param *pParams)
1346 {
1347 	struct hpt_iop_request_ioctl_command *req;
1348 
1349 	if ((pParams->Magic != HPT_IOCTL_MAGIC) &&
1350 		(pParams->Magic != HPT_IOCTL_MAGIC32))
1351 		return EFAULT;
1352 
1353 	req = (struct hpt_iop_request_ioctl_command *)(hba->ctlcfg_ptr);
1354 	hba->config_done = 0;
1355 	hptiop_lock_adapter(hba);
1356 	if (pParams->nInBufferSize)
1357 		if (copyin((void *)pParams->lpInBuffer,
1358 				req->buf, pParams->nInBufferSize))
1359 			goto invalid;
1360 	if (hptiop_post_ioctl_command_mvfrey(hba, req, pParams))
1361 		goto invalid;
1362 
1363 	if (hba->config_done == 1) {
1364 		if (pParams->nOutBufferSize)
1365 			if (copyout(req->buf +
1366 				((pParams->nInBufferSize + 3) & ~3),
1367 				(void *)pParams->lpOutBuffer,
1368 				pParams->nOutBufferSize))
1369 				goto invalid;
1370 
1371 		if (pParams->lpBytesReturned)
1372 			if (copyout(&req->bytes_returned,
1373 				(void*)pParams->lpBytesReturned,
1374 				sizeof(u_int32_t)))
1375 				goto invalid;
1376 		hptiop_unlock_adapter(hba);
1377 		return 0;
1378 	} else{
1379 invalid:
1380 		hptiop_unlock_adapter(hba);
1381 		return EFAULT;
1382 	}
1383 }
1384 
1385 static int  hptiop_rescan_bus(struct hpt_iop_hba * hba)
1386 {
1387 	union ccb           *ccb;
1388 
1389 	if ((ccb = xpt_alloc_ccb()) == NULL)
1390 		return(ENOMEM);
1391 	if (xpt_create_path(&ccb->ccb_h.path, NULL, cam_sim_path(hba->sim),
1392 		CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
1393 		xpt_free_ccb(ccb);
1394 		return(EIO);
1395 	}
1396 	xpt_rescan(ccb);
1397 	return(0);
1398 }
1399 
1400 static  bus_dmamap_callback_t   hptiop_map_srb;
1401 static  bus_dmamap_callback_t   hptiop_post_scsi_command;
1402 static  bus_dmamap_callback_t   hptiop_mv_map_ctlcfg;
1403 static	bus_dmamap_callback_t	hptiop_mvfrey_map_ctlcfg;
1404 
1405 static int hptiop_alloc_pci_res_itl(struct hpt_iop_hba *hba)
1406 {
1407 	hba->bar0_rid = 0x10;
1408 	hba->bar0_res = bus_alloc_resource_any(hba->pcidev,
1409 			SYS_RES_MEMORY, &hba->bar0_rid, RF_ACTIVE);
1410 
1411 	if (hba->bar0_res == NULL) {
1412 		device_printf(hba->pcidev,
1413 			"failed to get iop base adrress.\n");
1414 		return -1;
1415 	}
1416 	hba->bar0t = rman_get_bustag(hba->bar0_res);
1417 	hba->bar0h = rman_get_bushandle(hba->bar0_res);
1418 	hba->u.itl.mu = (struct hpt_iopmu_itl *)
1419 				rman_get_virtual(hba->bar0_res);
1420 
1421 	if (!hba->u.itl.mu) {
1422 		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1423 					hba->bar0_rid, hba->bar0_res);
1424 		device_printf(hba->pcidev, "alloc mem res failed\n");
1425 		return -1;
1426 	}
1427 
1428 	return 0;
1429 }
1430 
1431 static int hptiop_alloc_pci_res_mv(struct hpt_iop_hba *hba)
1432 {
1433 	hba->bar0_rid = 0x10;
1434 	hba->bar0_res = bus_alloc_resource_any(hba->pcidev,
1435 			SYS_RES_MEMORY, &hba->bar0_rid, RF_ACTIVE);
1436 
1437 	if (hba->bar0_res == NULL) {
1438 		device_printf(hba->pcidev, "failed to get iop bar0.\n");
1439 		return -1;
1440 	}
1441 	hba->bar0t = rman_get_bustag(hba->bar0_res);
1442 	hba->bar0h = rman_get_bushandle(hba->bar0_res);
1443 	hba->u.mv.regs = (struct hpt_iopmv_regs *)
1444 				rman_get_virtual(hba->bar0_res);
1445 
1446 	if (!hba->u.mv.regs) {
1447 		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1448 					hba->bar0_rid, hba->bar0_res);
1449 		device_printf(hba->pcidev, "alloc bar0 mem res failed\n");
1450 		return -1;
1451 	}
1452 
1453 	hba->bar2_rid = 0x18;
1454 	hba->bar2_res = bus_alloc_resource_any(hba->pcidev,
1455 			SYS_RES_MEMORY, &hba->bar2_rid, RF_ACTIVE);
1456 
1457 	if (hba->bar2_res == NULL) {
1458 		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1459 					hba->bar0_rid, hba->bar0_res);
1460 		device_printf(hba->pcidev, "failed to get iop bar2.\n");
1461 		return -1;
1462 	}
1463 
1464 	hba->bar2t = rman_get_bustag(hba->bar2_res);
1465 	hba->bar2h = rman_get_bushandle(hba->bar2_res);
1466 	hba->u.mv.mu = (struct hpt_iopmu_mv *)rman_get_virtual(hba->bar2_res);
1467 
1468 	if (!hba->u.mv.mu) {
1469 		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1470 					hba->bar0_rid, hba->bar0_res);
1471 		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1472 					hba->bar2_rid, hba->bar2_res);
1473 		device_printf(hba->pcidev, "alloc mem bar2 res failed\n");
1474 		return -1;
1475 	}
1476 
1477 	return 0;
1478 }
1479 
1480 static int hptiop_alloc_pci_res_mvfrey(struct hpt_iop_hba *hba)
1481 {
1482 	hba->bar0_rid = 0x10;
1483 	hba->bar0_res = bus_alloc_resource_any(hba->pcidev,
1484 			SYS_RES_MEMORY, &hba->bar0_rid, RF_ACTIVE);
1485 
1486 	if (hba->bar0_res == NULL) {
1487 		device_printf(hba->pcidev, "failed to get iop bar0.\n");
1488 		return -1;
1489 	}
1490 	hba->bar0t = rman_get_bustag(hba->bar0_res);
1491 	hba->bar0h = rman_get_bushandle(hba->bar0_res);
1492 	hba->u.mvfrey.config = (struct hpt_iop_request_get_config *)
1493 				rman_get_virtual(hba->bar0_res);
1494 
1495 	if (!hba->u.mvfrey.config) {
1496 		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1497 					hba->bar0_rid, hba->bar0_res);
1498 		device_printf(hba->pcidev, "alloc bar0 mem res failed\n");
1499 		return -1;
1500 	}
1501 
1502 	hba->bar2_rid = 0x18;
1503 	hba->bar2_res = bus_alloc_resource_any(hba->pcidev,
1504 			SYS_RES_MEMORY, &hba->bar2_rid, RF_ACTIVE);
1505 
1506 	if (hba->bar2_res == NULL) {
1507 		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1508 					hba->bar0_rid, hba->bar0_res);
1509 		device_printf(hba->pcidev, "failed to get iop bar2.\n");
1510 		return -1;
1511 	}
1512 
1513 	hba->bar2t = rman_get_bustag(hba->bar2_res);
1514 	hba->bar2h = rman_get_bushandle(hba->bar2_res);
1515 	hba->u.mvfrey.mu =
1516 					(struct hpt_iopmu_mvfrey *)rman_get_virtual(hba->bar2_res);
1517 
1518 	if (!hba->u.mvfrey.mu) {
1519 		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1520 					hba->bar0_rid, hba->bar0_res);
1521 		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1522 					hba->bar2_rid, hba->bar2_res);
1523 		device_printf(hba->pcidev, "alloc mem bar2 res failed\n");
1524 		return -1;
1525 	}
1526 
1527 	return 0;
1528 }
1529 
1530 static void hptiop_release_pci_res_itl(struct hpt_iop_hba *hba)
1531 {
1532 	if (hba->bar0_res)
1533 		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1534 			hba->bar0_rid, hba->bar0_res);
1535 }
1536 
1537 static void hptiop_release_pci_res_mv(struct hpt_iop_hba *hba)
1538 {
1539 	if (hba->bar0_res)
1540 		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1541 			hba->bar0_rid, hba->bar0_res);
1542 	if (hba->bar2_res)
1543 		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1544 			hba->bar2_rid, hba->bar2_res);
1545 }
1546 
1547 static void hptiop_release_pci_res_mvfrey(struct hpt_iop_hba *hba)
1548 {
1549 	if (hba->bar0_res)
1550 		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1551 			hba->bar0_rid, hba->bar0_res);
1552 	if (hba->bar2_res)
1553 		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1554 			hba->bar2_rid, hba->bar2_res);
1555 }
1556 
1557 static int hptiop_internal_memalloc_mv(struct hpt_iop_hba *hba)
1558 {
1559 	if (bus_dma_tag_create(hba->parent_dmat,
1560 				1,
1561 				0,
1562 				BUS_SPACE_MAXADDR_32BIT,
1563 				BUS_SPACE_MAXADDR,
1564 				NULL, NULL,
1565 				0x800 - 0x8,
1566 				1,
1567 				BUS_SPACE_MAXSIZE_32BIT,
1568 				BUS_DMA_ALLOCNOW,
1569 				NULL,
1570 				NULL,
1571 				&hba->ctlcfg_dmat)) {
1572 		device_printf(hba->pcidev, "alloc ctlcfg_dmat failed\n");
1573 		return -1;
1574 	}
1575 
1576 	if (bus_dmamem_alloc(hba->ctlcfg_dmat, (void **)&hba->ctlcfg_ptr,
1577 		BUS_DMA_WAITOK | BUS_DMA_COHERENT,
1578 		&hba->ctlcfg_dmamap) != 0) {
1579 			device_printf(hba->pcidev,
1580 					"bus_dmamem_alloc failed!\n");
1581 			bus_dma_tag_destroy(hba->ctlcfg_dmat);
1582 			return -1;
1583 	}
1584 
1585 	if (bus_dmamap_load(hba->ctlcfg_dmat,
1586 			hba->ctlcfg_dmamap, hba->ctlcfg_ptr,
1587 			MVIOP_IOCTLCFG_SIZE,
1588 			hptiop_mv_map_ctlcfg, hba, 0)) {
1589 		device_printf(hba->pcidev, "bus_dmamap_load failed!\n");
1590 		if (hba->ctlcfg_dmat) {
1591 			bus_dmamem_free(hba->ctlcfg_dmat,
1592 				hba->ctlcfg_ptr, hba->ctlcfg_dmamap);
1593 			bus_dma_tag_destroy(hba->ctlcfg_dmat);
1594 		}
1595 		return -1;
1596 	}
1597 
1598 	return 0;
1599 }
1600 
1601 static int hptiop_internal_memalloc_mvfrey(struct hpt_iop_hba *hba)
1602 {
1603 	u_int32_t list_count = BUS_SPACE_RD4_MVFREY2(inbound_conf_ctl);
1604 
1605 	list_count >>= 16;
1606 
1607 	if (list_count == 0) {
1608 		return -1;
1609 	}
1610 
1611 	hba->u.mvfrey.list_count = list_count;
1612 	hba->u.mvfrey.internal_mem_size = 0x800
1613 							+ list_count * sizeof(struct mvfrey_inlist_entry)
1614 							+ list_count * sizeof(struct mvfrey_outlist_entry)
1615 							+ sizeof(int);
1616 	if (bus_dma_tag_create(hba->parent_dmat,
1617 				1,
1618 				0,
1619 				BUS_SPACE_MAXADDR_32BIT,
1620 				BUS_SPACE_MAXADDR,
1621 				NULL, NULL,
1622 				hba->u.mvfrey.internal_mem_size,
1623 				1,
1624 				BUS_SPACE_MAXSIZE_32BIT,
1625 				BUS_DMA_ALLOCNOW,
1626 				NULL,
1627 				NULL,
1628 				&hba->ctlcfg_dmat)) {
1629 		device_printf(hba->pcidev, "alloc ctlcfg_dmat failed\n");
1630 		return -1;
1631 	}
1632 
1633 	if (bus_dmamem_alloc(hba->ctlcfg_dmat, (void **)&hba->ctlcfg_ptr,
1634 		BUS_DMA_WAITOK | BUS_DMA_COHERENT,
1635 		&hba->ctlcfg_dmamap) != 0) {
1636 			device_printf(hba->pcidev,
1637 					"bus_dmamem_alloc failed!\n");
1638 			bus_dma_tag_destroy(hba->ctlcfg_dmat);
1639 			return -1;
1640 	}
1641 
1642 	if (bus_dmamap_load(hba->ctlcfg_dmat,
1643 			hba->ctlcfg_dmamap, hba->ctlcfg_ptr,
1644 			hba->u.mvfrey.internal_mem_size,
1645 			hptiop_mvfrey_map_ctlcfg, hba, 0)) {
1646 		device_printf(hba->pcidev, "bus_dmamap_load failed!\n");
1647 		if (hba->ctlcfg_dmat) {
1648 			bus_dmamem_free(hba->ctlcfg_dmat,
1649 				hba->ctlcfg_ptr, hba->ctlcfg_dmamap);
1650 			bus_dma_tag_destroy(hba->ctlcfg_dmat);
1651 		}
1652 		return -1;
1653 	}
1654 
1655 	return 0;
1656 }
1657 
1658 static int hptiop_internal_memfree_itl(struct hpt_iop_hba *hba) {
1659 	return 0;
1660 }
1661 
1662 static int hptiop_internal_memfree_mv(struct hpt_iop_hba *hba)
1663 {
1664 	if (hba->ctlcfg_dmat) {
1665 		bus_dmamap_unload(hba->ctlcfg_dmat, hba->ctlcfg_dmamap);
1666 		bus_dmamem_free(hba->ctlcfg_dmat,
1667 					hba->ctlcfg_ptr, hba->ctlcfg_dmamap);
1668 		bus_dma_tag_destroy(hba->ctlcfg_dmat);
1669 	}
1670 
1671 	return 0;
1672 }
1673 
1674 static int hptiop_internal_memfree_mvfrey(struct hpt_iop_hba *hba)
1675 {
1676 	if (hba->ctlcfg_dmat) {
1677 		bus_dmamap_unload(hba->ctlcfg_dmat, hba->ctlcfg_dmamap);
1678 		bus_dmamem_free(hba->ctlcfg_dmat,
1679 					hba->ctlcfg_ptr, hba->ctlcfg_dmamap);
1680 		bus_dma_tag_destroy(hba->ctlcfg_dmat);
1681 	}
1682 
1683 	return 0;
1684 }
1685 
1686 static int hptiop_reset_comm_mvfrey(struct hpt_iop_hba *hba)
1687 {
1688 	u_int32_t i = 100;
1689 
1690 	if (hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_RESET_COMM, 3000))
1691 		return -1;
1692 
1693 	/* wait 100ms for MCU ready */
1694 	while(i--) {
1695 		DELAY(1000);
1696 	}
1697 
1698 	BUS_SPACE_WRT4_MVFREY2(inbound_base,
1699 							hba->u.mvfrey.inlist_phy & 0xffffffff);
1700 	BUS_SPACE_WRT4_MVFREY2(inbound_base_high,
1701 							(hba->u.mvfrey.inlist_phy >> 16) >> 16);
1702 
1703 	BUS_SPACE_WRT4_MVFREY2(outbound_base,
1704 							hba->u.mvfrey.outlist_phy & 0xffffffff);
1705 	BUS_SPACE_WRT4_MVFREY2(outbound_base_high,
1706 							(hba->u.mvfrey.outlist_phy >> 16) >> 16);
1707 
1708 	BUS_SPACE_WRT4_MVFREY2(outbound_shadow_base,
1709 							hba->u.mvfrey.outlist_cptr_phy & 0xffffffff);
1710 	BUS_SPACE_WRT4_MVFREY2(outbound_shadow_base_high,
1711 							(hba->u.mvfrey.outlist_cptr_phy >> 16) >> 16);
1712 
1713 	hba->u.mvfrey.inlist_wptr = (hba->u.mvfrey.list_count - 1)
1714 								| CL_POINTER_TOGGLE;
1715 	*hba->u.mvfrey.outlist_cptr = (hba->u.mvfrey.list_count - 1)
1716 								| CL_POINTER_TOGGLE;
1717 	hba->u.mvfrey.outlist_rptr = hba->u.mvfrey.list_count - 1;
1718 
1719 	return 0;
1720 }
1721 
1722 /*
1723  * CAM driver interface
1724  */
1725 static device_method_t driver_methods[] = {
1726 	/* Device interface */
1727 	DEVMETHOD(device_probe,     hptiop_probe),
1728 	DEVMETHOD(device_attach,    hptiop_attach),
1729 	DEVMETHOD(device_detach,    hptiop_detach),
1730 	DEVMETHOD(device_shutdown,  hptiop_shutdown),
1731 	{ 0, 0 }
1732 };
1733 
1734 static struct hptiop_adapter_ops hptiop_itl_ops = {
1735 	.family	           = INTEL_BASED_IOP,
1736 	.iop_wait_ready    = hptiop_wait_ready_itl,
1737 	.internal_memalloc = 0,
1738 	.internal_memfree  = hptiop_internal_memfree_itl,
1739 	.alloc_pci_res     = hptiop_alloc_pci_res_itl,
1740 	.release_pci_res   = hptiop_release_pci_res_itl,
1741 	.enable_intr       = hptiop_enable_intr_itl,
1742 	.disable_intr      = hptiop_disable_intr_itl,
1743 	.get_config        = hptiop_get_config_itl,
1744 	.set_config        = hptiop_set_config_itl,
1745 	.iop_intr          = hptiop_intr_itl,
1746 	.post_msg          = hptiop_post_msg_itl,
1747 	.post_req          = hptiop_post_req_itl,
1748 	.do_ioctl          = hptiop_do_ioctl_itl,
1749 	.reset_comm        = 0,
1750 };
1751 
1752 static struct hptiop_adapter_ops hptiop_mv_ops = {
1753 	.family	           = MV_BASED_IOP,
1754 	.iop_wait_ready    = hptiop_wait_ready_mv,
1755 	.internal_memalloc = hptiop_internal_memalloc_mv,
1756 	.internal_memfree  = hptiop_internal_memfree_mv,
1757 	.alloc_pci_res     = hptiop_alloc_pci_res_mv,
1758 	.release_pci_res   = hptiop_release_pci_res_mv,
1759 	.enable_intr       = hptiop_enable_intr_mv,
1760 	.disable_intr      = hptiop_disable_intr_mv,
1761 	.get_config        = hptiop_get_config_mv,
1762 	.set_config        = hptiop_set_config_mv,
1763 	.iop_intr          = hptiop_intr_mv,
1764 	.post_msg          = hptiop_post_msg_mv,
1765 	.post_req          = hptiop_post_req_mv,
1766 	.do_ioctl          = hptiop_do_ioctl_mv,
1767 	.reset_comm        = 0,
1768 };
1769 
1770 static struct hptiop_adapter_ops hptiop_mvfrey_ops = {
1771 	.family	           = MVFREY_BASED_IOP,
1772 	.iop_wait_ready    = hptiop_wait_ready_mvfrey,
1773 	.internal_memalloc = hptiop_internal_memalloc_mvfrey,
1774 	.internal_memfree  = hptiop_internal_memfree_mvfrey,
1775 	.alloc_pci_res     = hptiop_alloc_pci_res_mvfrey,
1776 	.release_pci_res   = hptiop_release_pci_res_mvfrey,
1777 	.enable_intr       = hptiop_enable_intr_mvfrey,
1778 	.disable_intr      = hptiop_disable_intr_mvfrey,
1779 	.get_config        = hptiop_get_config_mvfrey,
1780 	.set_config        = hptiop_set_config_mvfrey,
1781 	.iop_intr          = hptiop_intr_mvfrey,
1782 	.post_msg          = hptiop_post_msg_mvfrey,
1783 	.post_req          = hptiop_post_req_mvfrey,
1784 	.do_ioctl          = hptiop_do_ioctl_mvfrey,
1785 	.reset_comm        = hptiop_reset_comm_mvfrey,
1786 };
1787 
1788 static driver_t hptiop_pci_driver = {
1789 	driver_name,
1790 	driver_methods,
1791 	sizeof(struct hpt_iop_hba)
1792 };
1793 
1794 DRIVER_MODULE(hptiop, pci, hptiop_pci_driver, 0, 0);
1795 MODULE_DEPEND(hptiop, cam, 1, 1, 1);
1796 
1797 static int hptiop_probe(device_t dev)
1798 {
1799 	struct hpt_iop_hba *hba;
1800 	u_int32_t id;
1801 	static char buf[256];
1802 	int sas = 0;
1803 	struct hptiop_adapter_ops *ops;
1804 
1805 	if (pci_get_vendor(dev) != 0x1103)
1806 		return (ENXIO);
1807 
1808 	id = pci_get_device(dev);
1809 
1810 	switch (id) {
1811 		case 0x4520:
1812 		case 0x4521:
1813 		case 0x4522:
1814 			sas = 1;
1815 		case 0x3620:
1816 		case 0x3622:
1817 		case 0x3640:
1818 			ops = &hptiop_mvfrey_ops;
1819 			break;
1820 		case 0x4210:
1821 		case 0x4211:
1822 		case 0x4310:
1823 		case 0x4311:
1824 		case 0x4320:
1825 		case 0x4321:
1826  		case 0x4322:
1827 			sas = 1;
1828 		case 0x3220:
1829 		case 0x3320:
1830 		case 0x3410:
1831 		case 0x3520:
1832 		case 0x3510:
1833 		case 0x3511:
1834 		case 0x3521:
1835 		case 0x3522:
1836 		case 0x3530:
1837 		case 0x3540:
1838 		case 0x3560:
1839 			ops = &hptiop_itl_ops;
1840 			break;
1841 		case 0x3020:
1842 		case 0x3120:
1843 		case 0x3122:
1844 			ops = &hptiop_mv_ops;
1845 			break;
1846 		default:
1847 			return (ENXIO);
1848 	}
1849 
1850 	device_printf(dev, "adapter at PCI %d:%d:%d, IRQ %d\n",
1851 		pci_get_bus(dev), pci_get_slot(dev),
1852 		pci_get_function(dev), pci_get_irq(dev));
1853 
1854 	sprintf(buf, "RocketRAID %x %s Controller\n",
1855 				id, sas ? "SAS" : "SATA");
1856 	device_set_desc_copy(dev, buf);
1857 
1858 	hba = (struct hpt_iop_hba *)device_get_softc(dev);
1859 	bzero(hba, sizeof(struct hpt_iop_hba));
1860 	hba->ops = ops;
1861 
1862 	KdPrint(("hba->ops=%p\n", hba->ops));
1863 	return 0;
1864 }
1865 
1866 static int hptiop_attach(device_t dev)
1867 {
1868 	struct make_dev_args args;
1869 	struct hpt_iop_hba *hba = (struct hpt_iop_hba *)device_get_softc(dev);
1870 	struct hpt_iop_request_get_config  iop_config;
1871 	struct hpt_iop_request_set_config  set_config;
1872 	int rid = 0;
1873 	struct cam_devq *devq;
1874 	struct ccb_setasync ccb;
1875 	u_int32_t unit = device_get_unit(dev);
1876 
1877 	device_printf(dev, "%d RocketRAID 3xxx/4xxx controller driver %s\n",
1878 			unit, driver_version);
1879 
1880 	KdPrint(("hptiop: attach(%d, %d/%d/%d) ops=%p\n", unit,
1881 		pci_get_bus(dev), pci_get_slot(dev),
1882 		pci_get_function(dev), hba->ops));
1883 
1884 	pci_enable_busmaster(dev);
1885 	hba->pcidev = dev;
1886 	hba->pciunit = unit;
1887 
1888 	if (hba->ops->alloc_pci_res(hba))
1889 		return ENXIO;
1890 
1891 	if (hba->ops->iop_wait_ready(hba, 2000)) {
1892 		device_printf(dev, "adapter is not ready\n");
1893 		goto release_pci_res;
1894 	}
1895 
1896 	mtx_init(&hba->lock, "hptioplock", NULL, MTX_DEF);
1897 
1898 	if (bus_dma_tag_create(bus_get_dma_tag(dev),/* PCI parent */
1899 			1,  /* alignment */
1900 			0, /* boundary */
1901 			BUS_SPACE_MAXADDR,  /* lowaddr */
1902 			BUS_SPACE_MAXADDR,  /* highaddr */
1903 			NULL, NULL,         /* filter, filterarg */
1904 			BUS_SPACE_MAXSIZE_32BIT,    /* maxsize */
1905 			BUS_SPACE_UNRESTRICTED, /* nsegments */
1906 			BUS_SPACE_MAXSIZE_32BIT,    /* maxsegsize */
1907 			0,      /* flags */
1908 			NULL,   /* lockfunc */
1909 			NULL,       /* lockfuncarg */
1910 			&hba->parent_dmat   /* tag */))
1911 	{
1912 		device_printf(dev, "alloc parent_dmat failed\n");
1913 		goto release_pci_res;
1914 	}
1915 
1916 	if (hba->ops->family == MV_BASED_IOP) {
1917 		if (hba->ops->internal_memalloc(hba)) {
1918 			device_printf(dev, "alloc srb_dmat failed\n");
1919 			goto destroy_parent_tag;
1920 		}
1921 	}
1922 
1923 	if (hba->ops->get_config(hba, &iop_config)) {
1924 		device_printf(dev, "get iop config failed.\n");
1925 		goto get_config_failed;
1926 	}
1927 
1928 	hba->firmware_version = iop_config.firmware_version;
1929 	hba->interface_version = iop_config.interface_version;
1930 	hba->max_requests = iop_config.max_requests;
1931 	hba->max_devices = iop_config.max_devices;
1932 	hba->max_request_size = iop_config.request_size;
1933 	hba->max_sg_count = iop_config.max_sg_count;
1934 
1935 	if (hba->ops->family == MVFREY_BASED_IOP) {
1936 		if (hba->ops->internal_memalloc(hba)) {
1937 			device_printf(dev, "alloc srb_dmat failed\n");
1938 			goto destroy_parent_tag;
1939 		}
1940 		if (hba->ops->reset_comm(hba)) {
1941 			device_printf(dev, "reset comm failed\n");
1942 			goto get_config_failed;
1943 		}
1944 	}
1945 
1946 	if (bus_dma_tag_create(hba->parent_dmat,/* parent */
1947 			4,  /* alignment */
1948 			BUS_SPACE_MAXADDR_32BIT+1, /* boundary */
1949 			BUS_SPACE_MAXADDR,  /* lowaddr */
1950 			BUS_SPACE_MAXADDR,  /* highaddr */
1951 			NULL, NULL,         /* filter, filterarg */
1952 			PAGE_SIZE * (hba->max_sg_count-1),  /* maxsize */
1953 			hba->max_sg_count,  /* nsegments */
1954 			0x20000,    /* maxsegsize */
1955 			BUS_DMA_ALLOCNOW,       /* flags */
1956 			busdma_lock_mutex,  /* lockfunc */
1957 			&hba->lock,     /* lockfuncarg */
1958 			&hba->io_dmat   /* tag */))
1959 	{
1960 		device_printf(dev, "alloc io_dmat failed\n");
1961 		goto get_config_failed;
1962 	}
1963 
1964 	if (bus_dma_tag_create(hba->parent_dmat,/* parent */
1965 			1,  /* alignment */
1966 			0, /* boundary */
1967 			BUS_SPACE_MAXADDR_32BIT,    /* lowaddr */
1968 			BUS_SPACE_MAXADDR,  /* highaddr */
1969 			NULL, NULL,         /* filter, filterarg */
1970 			HPT_SRB_MAX_SIZE * HPT_SRB_MAX_QUEUE_SIZE + 0x20,
1971 			1,  /* nsegments */
1972 			BUS_SPACE_MAXSIZE_32BIT,    /* maxsegsize */
1973 			0,      /* flags */
1974 			NULL,   /* lockfunc */
1975 			NULL,       /* lockfuncarg */
1976 			&hba->srb_dmat  /* tag */))
1977 	{
1978 		device_printf(dev, "alloc srb_dmat failed\n");
1979 		goto destroy_io_dmat;
1980 	}
1981 
1982 	if (bus_dmamem_alloc(hba->srb_dmat, (void **)&hba->uncached_ptr,
1983 			BUS_DMA_WAITOK | BUS_DMA_COHERENT,
1984 			&hba->srb_dmamap) != 0)
1985 	{
1986 		device_printf(dev, "srb bus_dmamem_alloc failed!\n");
1987 		goto destroy_srb_dmat;
1988 	}
1989 
1990 	if (bus_dmamap_load(hba->srb_dmat,
1991 			hba->srb_dmamap, hba->uncached_ptr,
1992 			(HPT_SRB_MAX_SIZE * HPT_SRB_MAX_QUEUE_SIZE) + 0x20,
1993 			hptiop_map_srb, hba, 0))
1994 	{
1995 		device_printf(dev, "bus_dmamap_load failed!\n");
1996 		goto srb_dmamem_free;
1997 	}
1998 
1999 	if ((devq = cam_simq_alloc(hba->max_requests - 1 )) == NULL) {
2000 		device_printf(dev, "cam_simq_alloc failed\n");
2001 		goto srb_dmamap_unload;
2002 	}
2003 
2004 	hba->sim = cam_sim_alloc(hptiop_action, hptiop_poll, driver_name,
2005 			hba, unit, &hba->lock, hba->max_requests - 1, 1, devq);
2006 	if (!hba->sim) {
2007 		device_printf(dev, "cam_sim_alloc failed\n");
2008 		cam_simq_free(devq);
2009 		goto srb_dmamap_unload;
2010 	}
2011 	hptiop_lock_adapter(hba);
2012 	if (xpt_bus_register(hba->sim, dev, 0) != CAM_SUCCESS)
2013 	{
2014 		device_printf(dev, "xpt_bus_register failed\n");
2015 		goto free_cam_sim;
2016 	}
2017 
2018 	if (xpt_create_path(&hba->path, /*periph */ NULL,
2019 			cam_sim_path(hba->sim), CAM_TARGET_WILDCARD,
2020 			CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
2021 		device_printf(dev, "xpt_create_path failed\n");
2022 		goto deregister_xpt_bus;
2023 	}
2024 	hptiop_unlock_adapter(hba);
2025 
2026 	bzero(&set_config, sizeof(set_config));
2027 	set_config.iop_id = unit;
2028 	set_config.vbus_id = cam_sim_path(hba->sim);
2029 	set_config.max_host_request_size = HPT_SRB_MAX_REQ_SIZE;
2030 
2031 	if (hba->ops->set_config(hba, &set_config)) {
2032 		device_printf(dev, "set iop config failed.\n");
2033 		goto free_hba_path;
2034 	}
2035 
2036 	memset(&ccb, 0, sizeof(ccb));
2037 	xpt_setup_ccb(&ccb.ccb_h, hba->path, /*priority*/5);
2038 	ccb.ccb_h.func_code = XPT_SASYNC_CB;
2039 	ccb.event_enable = (AC_FOUND_DEVICE | AC_LOST_DEVICE);
2040 	ccb.callback = hptiop_async;
2041 	ccb.callback_arg = hba->sim;
2042 	xpt_action((union ccb *)&ccb);
2043 
2044 	rid = 0;
2045 	if ((hba->irq_res = bus_alloc_resource_any(hba->pcidev, SYS_RES_IRQ,
2046 			&rid, RF_SHAREABLE | RF_ACTIVE)) == NULL) {
2047 		device_printf(dev, "allocate irq failed!\n");
2048 		goto free_hba_path;
2049 	}
2050 
2051 	if (bus_setup_intr(hba->pcidev, hba->irq_res, INTR_TYPE_CAM | INTR_MPSAFE,
2052 				NULL, hptiop_pci_intr, hba, &hba->irq_handle))
2053 	{
2054 		device_printf(dev, "allocate intr function failed!\n");
2055 		goto free_irq_resource;
2056 	}
2057 
2058 	if (hptiop_send_sync_msg(hba,
2059 			IOPMU_INBOUND_MSG0_START_BACKGROUND_TASK, 5000)) {
2060 		device_printf(dev, "fail to start background task\n");
2061 		goto teartown_irq_resource;
2062 	}
2063 
2064 	hba->ops->enable_intr(hba);
2065 	hba->initialized = 1;
2066 
2067 	make_dev_args_init(&args);
2068 	args.mda_devsw = &hptiop_cdevsw;
2069 	args.mda_uid = UID_ROOT;
2070 	args.mda_gid = GID_WHEEL /*GID_OPERATOR*/;
2071 	args.mda_mode = S_IRUSR | S_IWUSR;
2072 	args.mda_si_drv1 = hba;
2073 
2074 	make_dev_s(&args, &hba->ioctl_dev, "%s%d", driver_name, unit);
2075 
2076 	return 0;
2077 
2078 
2079 teartown_irq_resource:
2080 	bus_teardown_intr(dev, hba->irq_res, hba->irq_handle);
2081 
2082 free_irq_resource:
2083 	bus_release_resource(dev, SYS_RES_IRQ, 0, hba->irq_res);
2084 
2085 	hptiop_lock_adapter(hba);
2086 free_hba_path:
2087 	xpt_free_path(hba->path);
2088 
2089 deregister_xpt_bus:
2090 	xpt_bus_deregister(cam_sim_path(hba->sim));
2091 
2092 free_cam_sim:
2093 	cam_sim_free(hba->sim, /*free devq*/ TRUE);
2094 	hptiop_unlock_adapter(hba);
2095 
2096 srb_dmamap_unload:
2097 	if (hba->uncached_ptr)
2098 		bus_dmamap_unload(hba->srb_dmat, hba->srb_dmamap);
2099 
2100 srb_dmamem_free:
2101 	if (hba->uncached_ptr)
2102 		bus_dmamem_free(hba->srb_dmat,
2103 			hba->uncached_ptr, hba->srb_dmamap);
2104 
2105 destroy_srb_dmat:
2106 	if (hba->srb_dmat)
2107 		bus_dma_tag_destroy(hba->srb_dmat);
2108 
2109 destroy_io_dmat:
2110 	if (hba->io_dmat)
2111 		bus_dma_tag_destroy(hba->io_dmat);
2112 
2113 get_config_failed:
2114 	hba->ops->internal_memfree(hba);
2115 
2116 destroy_parent_tag:
2117 	if (hba->parent_dmat)
2118 		bus_dma_tag_destroy(hba->parent_dmat);
2119 
2120 release_pci_res:
2121 	if (hba->ops->release_pci_res)
2122 		hba->ops->release_pci_res(hba);
2123 
2124 	return ENXIO;
2125 }
2126 
2127 static int hptiop_detach(device_t dev)
2128 {
2129 	struct hpt_iop_hba * hba = (struct hpt_iop_hba *)device_get_softc(dev);
2130 	int i;
2131 	int error = EBUSY;
2132 
2133 	hptiop_lock_adapter(hba);
2134 	for (i = 0; i < hba->max_devices; i++)
2135 		if (hptiop_os_query_remove_device(hba, i)) {
2136 			device_printf(dev, "%d file system is busy. id=%d",
2137 						hba->pciunit, i);
2138 			goto out;
2139 		}
2140 
2141 	if ((error = hptiop_shutdown(dev)) != 0)
2142 		goto out;
2143 	if (hptiop_send_sync_msg(hba,
2144 		IOPMU_INBOUND_MSG0_STOP_BACKGROUND_TASK, 60000))
2145 		goto out;
2146 	hptiop_unlock_adapter(hba);
2147 
2148 	hptiop_release_resource(hba);
2149 	return (0);
2150 out:
2151 	hptiop_unlock_adapter(hba);
2152 	return error;
2153 }
2154 
2155 static int hptiop_shutdown(device_t dev)
2156 {
2157 	struct hpt_iop_hba * hba = (struct hpt_iop_hba *)device_get_softc(dev);
2158 
2159 	int error = 0;
2160 
2161 	if (hba->flag & HPT_IOCTL_FLAG_OPEN) {
2162 		device_printf(dev, "%d device is busy", hba->pciunit);
2163 		return EBUSY;
2164 	}
2165 
2166 	hba->ops->disable_intr(hba);
2167 
2168 	if (hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_SHUTDOWN, 60000))
2169 		error = EBUSY;
2170 
2171 	return error;
2172 }
2173 
2174 static void hptiop_pci_intr(void *arg)
2175 {
2176 	struct hpt_iop_hba * hba = (struct hpt_iop_hba *)arg;
2177 	hptiop_lock_adapter(hba);
2178 	hba->ops->iop_intr(hba);
2179 	hptiop_unlock_adapter(hba);
2180 }
2181 
2182 static void hptiop_poll(struct cam_sim *sim)
2183 {
2184 	struct hpt_iop_hba *hba;
2185 
2186 	hba = cam_sim_softc(sim);
2187 	hba->ops->iop_intr(hba);
2188 }
2189 
2190 static void hptiop_async(void * callback_arg, u_int32_t code,
2191 					struct cam_path * path, void * arg)
2192 {
2193 }
2194 
2195 static void hptiop_enable_intr_itl(struct hpt_iop_hba *hba)
2196 {
2197 	BUS_SPACE_WRT4_ITL(outbound_intmask,
2198 		~(IOPMU_OUTBOUND_INT_POSTQUEUE | IOPMU_OUTBOUND_INT_MSG0));
2199 }
2200 
2201 static void hptiop_enable_intr_mv(struct hpt_iop_hba *hba)
2202 {
2203 	u_int32_t int_mask;
2204 
2205 	int_mask = BUS_SPACE_RD4_MV0(outbound_intmask);
2206 
2207 	int_mask |= MVIOP_MU_OUTBOUND_INT_POSTQUEUE
2208 			| MVIOP_MU_OUTBOUND_INT_MSG;
2209     	BUS_SPACE_WRT4_MV0(outbound_intmask,int_mask);
2210 }
2211 
2212 static void hptiop_enable_intr_mvfrey(struct hpt_iop_hba *hba)
2213 {
2214 	BUS_SPACE_WRT4_MVFREY2(f0_doorbell_enable, CPU_TO_F0_DRBL_MSG_A_BIT);
2215 	BUS_SPACE_RD4_MVFREY2(f0_doorbell_enable);
2216 
2217 	BUS_SPACE_WRT4_MVFREY2(isr_enable, 0x1);
2218 	BUS_SPACE_RD4_MVFREY2(isr_enable);
2219 
2220 	BUS_SPACE_WRT4_MVFREY2(pcie_f0_int_enable, 0x1010);
2221 	BUS_SPACE_RD4_MVFREY2(pcie_f0_int_enable);
2222 }
2223 
2224 static void hptiop_disable_intr_itl(struct hpt_iop_hba *hba)
2225 {
2226 	u_int32_t int_mask;
2227 
2228 	int_mask = BUS_SPACE_RD4_ITL(outbound_intmask);
2229 
2230 	int_mask |= IOPMU_OUTBOUND_INT_POSTQUEUE | IOPMU_OUTBOUND_INT_MSG0;
2231 	BUS_SPACE_WRT4_ITL(outbound_intmask, int_mask);
2232 	BUS_SPACE_RD4_ITL(outbound_intstatus);
2233 }
2234 
2235 static void hptiop_disable_intr_mv(struct hpt_iop_hba *hba)
2236 {
2237 	u_int32_t int_mask;
2238 	int_mask = BUS_SPACE_RD4_MV0(outbound_intmask);
2239 
2240 	int_mask &= ~(MVIOP_MU_OUTBOUND_INT_MSG
2241 			| MVIOP_MU_OUTBOUND_INT_POSTQUEUE);
2242 	BUS_SPACE_WRT4_MV0(outbound_intmask,int_mask);
2243 	BUS_SPACE_RD4_MV0(outbound_intmask);
2244 }
2245 
2246 static void hptiop_disable_intr_mvfrey(struct hpt_iop_hba *hba)
2247 {
2248 	BUS_SPACE_WRT4_MVFREY2(f0_doorbell_enable, 0);
2249 	BUS_SPACE_RD4_MVFREY2(f0_doorbell_enable);
2250 
2251 	BUS_SPACE_WRT4_MVFREY2(isr_enable, 0);
2252 	BUS_SPACE_RD4_MVFREY2(isr_enable);
2253 
2254 	BUS_SPACE_WRT4_MVFREY2(pcie_f0_int_enable, 0);
2255 	BUS_SPACE_RD4_MVFREY2(pcie_f0_int_enable);
2256 }
2257 
2258 static void hptiop_reset_adapter(void *argv)
2259 {
2260 	struct hpt_iop_hba * hba = (struct hpt_iop_hba *)argv;
2261 	if (hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_RESET, 60000))
2262 		return;
2263 	hptiop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_START_BACKGROUND_TASK, 5000);
2264 }
2265 
2266 static void *hptiop_get_srb(struct hpt_iop_hba * hba)
2267 {
2268 	struct hpt_iop_srb * srb;
2269 
2270 	if (hba->srb_list) {
2271 		srb = hba->srb_list;
2272 		hba->srb_list = srb->next;
2273 		return srb;
2274 	}
2275 
2276 	return NULL;
2277 }
2278 
2279 static void hptiop_free_srb(struct hpt_iop_hba *hba, struct hpt_iop_srb *srb)
2280 {
2281 	srb->next = hba->srb_list;
2282 	hba->srb_list = srb;
2283 }
2284 
2285 static void hptiop_action(struct cam_sim *sim, union ccb *ccb)
2286 {
2287 	struct hpt_iop_hba * hba = (struct hpt_iop_hba *)cam_sim_softc(sim);
2288 	struct hpt_iop_srb * srb;
2289 	int error;
2290 
2291 	switch (ccb->ccb_h.func_code) {
2292 
2293 	case XPT_SCSI_IO:
2294 		if (ccb->ccb_h.target_lun != 0 ||
2295 			ccb->ccb_h.target_id >= hba->max_devices ||
2296 			(ccb->ccb_h.flags & CAM_CDB_PHYS))
2297 		{
2298 			ccb->ccb_h.status = CAM_TID_INVALID;
2299 			xpt_done(ccb);
2300 			return;
2301 		}
2302 
2303 		if ((srb = hptiop_get_srb(hba)) == NULL) {
2304 			device_printf(hba->pcidev, "srb allocated failed");
2305 			ccb->ccb_h.status = CAM_REQ_CMP_ERR;
2306 			xpt_done(ccb);
2307 			return;
2308 		}
2309 
2310 		srb->ccb = ccb;
2311 		error = bus_dmamap_load_ccb(hba->io_dmat,
2312 					    srb->dma_map,
2313 					    ccb,
2314 					    hptiop_post_scsi_command,
2315 					    srb,
2316 					    0);
2317 
2318 		if (error && error != EINPROGRESS) {
2319 			device_printf(hba->pcidev,
2320 				"%d bus_dmamap_load error %d",
2321 				hba->pciunit, error);
2322 			xpt_freeze_simq(hba->sim, 1);
2323 			ccb->ccb_h.status = CAM_REQ_CMP_ERR;
2324 			hptiop_free_srb(hba, srb);
2325 			xpt_done(ccb);
2326 			return;
2327 		}
2328 
2329 		return;
2330 
2331 	case XPT_RESET_BUS:
2332 		device_printf(hba->pcidev, "reset adapter");
2333 		hba->msg_done = 0;
2334 		hptiop_reset_adapter(hba);
2335 		break;
2336 
2337 	case XPT_GET_TRAN_SETTINGS:
2338 	case XPT_SET_TRAN_SETTINGS:
2339 		ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
2340 		break;
2341 
2342 	case XPT_CALC_GEOMETRY:
2343 		cam_calc_geometry(&ccb->ccg, 1);
2344 		break;
2345 
2346 	case XPT_PATH_INQ:
2347 	{
2348 		struct ccb_pathinq *cpi = &ccb->cpi;
2349 
2350 		cpi->version_num = 1;
2351 		cpi->hba_inquiry = PI_SDTR_ABLE;
2352 		cpi->target_sprt = 0;
2353 		cpi->hba_misc = PIM_NOBUSRESET;
2354 		cpi->hba_eng_cnt = 0;
2355 		cpi->max_target = hba->max_devices;
2356 		cpi->max_lun = 0;
2357 		cpi->unit_number = cam_sim_unit(sim);
2358 		cpi->bus_id = cam_sim_bus(sim);
2359 		cpi->initiator_id = hba->max_devices;
2360 		cpi->base_transfer_speed = 3300;
2361 
2362 		strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
2363 		strlcpy(cpi->hba_vid, "HPT   ", HBA_IDLEN);
2364 		strlcpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
2365 		cpi->transport = XPORT_SPI;
2366 		cpi->transport_version = 2;
2367 		cpi->protocol = PROTO_SCSI;
2368 		cpi->protocol_version = SCSI_REV_2;
2369 		cpi->ccb_h.status = CAM_REQ_CMP;
2370 		break;
2371 	}
2372 
2373 	default:
2374 		ccb->ccb_h.status = CAM_REQ_INVALID;
2375 		break;
2376 	}
2377 
2378 	xpt_done(ccb);
2379 	return;
2380 }
2381 
2382 static void hptiop_post_req_itl(struct hpt_iop_hba *hba,
2383 				struct hpt_iop_srb *srb,
2384 				bus_dma_segment_t *segs, int nsegs)
2385 {
2386 	int idx;
2387 	union ccb *ccb = srb->ccb;
2388 	u_int8_t *cdb;
2389 
2390 	if (ccb->ccb_h.flags & CAM_CDB_POINTER)
2391 		cdb = ccb->csio.cdb_io.cdb_ptr;
2392 	else
2393 		cdb = ccb->csio.cdb_io.cdb_bytes;
2394 
2395 	KdPrint(("ccb=%p %x-%x-%x\n",
2396 		ccb, *(u_int32_t *)cdb, *((u_int32_t *)cdb+1), *((u_int32_t *)cdb+2)));
2397 
2398 	if (srb->srb_flag & HPT_SRB_FLAG_HIGH_MEM_ACESS) {
2399 		u_int32_t iop_req32;
2400 		struct hpt_iop_request_scsi_command req;
2401 
2402 		iop_req32 = BUS_SPACE_RD4_ITL(inbound_queue);
2403 
2404 		if (iop_req32 == IOPMU_QUEUE_EMPTY) {
2405 			device_printf(hba->pcidev, "invalid req offset\n");
2406 			ccb->ccb_h.status = CAM_BUSY;
2407 			bus_dmamap_unload(hba->io_dmat, srb->dma_map);
2408 			hptiop_free_srb(hba, srb);
2409 			xpt_done(ccb);
2410 			return;
2411 		}
2412 
2413 		if (ccb->csio.dxfer_len && nsegs > 0) {
2414 			struct hpt_iopsg *psg = req.sg_list;
2415 			for (idx = 0; idx < nsegs; idx++, psg++) {
2416 				psg->pci_address = (u_int64_t)segs[idx].ds_addr;
2417 				psg->size = segs[idx].ds_len;
2418 				psg->eot = 0;
2419 			}
2420 			psg[-1].eot = 1;
2421 		}
2422 
2423 		bcopy(cdb, req.cdb, ccb->csio.cdb_len);
2424 
2425 		req.header.size =
2426 				offsetof(struct hpt_iop_request_scsi_command, sg_list)
2427 				+ nsegs*sizeof(struct hpt_iopsg);
2428 		req.header.type = IOP_REQUEST_TYPE_SCSI_COMMAND;
2429 		req.header.flags = 0;
2430 		req.header.result = IOP_RESULT_PENDING;
2431 		req.header.context = (u_int64_t)(unsigned long)srb;
2432 		req.dataxfer_length = ccb->csio.dxfer_len;
2433 		req.channel =  0;
2434 		req.target =  ccb->ccb_h.target_id;
2435 		req.lun =  ccb->ccb_h.target_lun;
2436 
2437 		bus_space_write_region_1(hba->bar0t, hba->bar0h, iop_req32,
2438 			(u_int8_t *)&req, req.header.size);
2439 
2440 		if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
2441 			bus_dmamap_sync(hba->io_dmat,
2442 				srb->dma_map, BUS_DMASYNC_PREREAD);
2443 		}
2444 		else if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT)
2445 			bus_dmamap_sync(hba->io_dmat,
2446 				srb->dma_map, BUS_DMASYNC_PREWRITE);
2447 
2448 		BUS_SPACE_WRT4_ITL(inbound_queue,iop_req32);
2449 	} else {
2450 		struct hpt_iop_request_scsi_command *req;
2451 
2452 		req = (struct hpt_iop_request_scsi_command *)srb;
2453 		if (ccb->csio.dxfer_len && nsegs > 0) {
2454 			struct hpt_iopsg *psg = req->sg_list;
2455 			for (idx = 0; idx < nsegs; idx++, psg++) {
2456 				psg->pci_address =
2457 					(u_int64_t)segs[idx].ds_addr;
2458 				psg->size = segs[idx].ds_len;
2459 				psg->eot = 0;
2460 			}
2461 			psg[-1].eot = 1;
2462 		}
2463 
2464 		bcopy(cdb, req->cdb, ccb->csio.cdb_len);
2465 
2466 		req->header.type = IOP_REQUEST_TYPE_SCSI_COMMAND;
2467 		req->header.result = IOP_RESULT_PENDING;
2468 		req->dataxfer_length = ccb->csio.dxfer_len;
2469 		req->channel =  0;
2470 		req->target =  ccb->ccb_h.target_id;
2471 		req->lun =  ccb->ccb_h.target_lun;
2472 		req->header.size =
2473 			offsetof(struct hpt_iop_request_scsi_command, sg_list)
2474 			+ nsegs*sizeof(struct hpt_iopsg);
2475 		req->header.context = (u_int64_t)srb->index |
2476 						IOPMU_QUEUE_ADDR_HOST_BIT;
2477 		req->header.flags = IOP_REQUEST_FLAG_OUTPUT_CONTEXT;
2478 
2479 		if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
2480 			bus_dmamap_sync(hba->io_dmat,
2481 				srb->dma_map, BUS_DMASYNC_PREREAD);
2482 		}else if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) {
2483 			bus_dmamap_sync(hba->io_dmat,
2484 				srb->dma_map, BUS_DMASYNC_PREWRITE);
2485 		}
2486 
2487 		if (hba->firmware_version > 0x01020000
2488 			|| hba->interface_version > 0x01020000) {
2489 			u_int32_t size_bits;
2490 
2491 			if (req->header.size < 256)
2492 				size_bits = IOPMU_QUEUE_REQUEST_SIZE_BIT;
2493 			else if (req->header.size < 512)
2494 				size_bits = IOPMU_QUEUE_ADDR_HOST_BIT;
2495 			else
2496 				size_bits = IOPMU_QUEUE_REQUEST_SIZE_BIT
2497 						| IOPMU_QUEUE_ADDR_HOST_BIT;
2498 
2499 			BUS_SPACE_WRT4_ITL(inbound_queue,
2500 				(u_int32_t)srb->phy_addr | size_bits);
2501 		} else
2502 			BUS_SPACE_WRT4_ITL(inbound_queue, (u_int32_t)srb->phy_addr
2503 				|IOPMU_QUEUE_ADDR_HOST_BIT);
2504 	}
2505 }
2506 
2507 static void hptiop_post_req_mv(struct hpt_iop_hba *hba,
2508 				struct hpt_iop_srb *srb,
2509 				bus_dma_segment_t *segs, int nsegs)
2510 {
2511 	int idx, size;
2512 	union ccb *ccb = srb->ccb;
2513 	u_int8_t *cdb;
2514 	struct hpt_iop_request_scsi_command *req;
2515 	u_int64_t req_phy;
2516 
2517     	req = (struct hpt_iop_request_scsi_command *)srb;
2518 	req_phy = srb->phy_addr;
2519 
2520 	if (ccb->csio.dxfer_len && nsegs > 0) {
2521 		struct hpt_iopsg *psg = req->sg_list;
2522 		for (idx = 0; idx < nsegs; idx++, psg++) {
2523 			psg->pci_address = (u_int64_t)segs[idx].ds_addr;
2524 			psg->size = segs[idx].ds_len;
2525 			psg->eot = 0;
2526 		}
2527 		psg[-1].eot = 1;
2528 	}
2529 	if (ccb->ccb_h.flags & CAM_CDB_POINTER)
2530 		cdb = ccb->csio.cdb_io.cdb_ptr;
2531 	else
2532 		cdb = ccb->csio.cdb_io.cdb_bytes;
2533 
2534 	bcopy(cdb, req->cdb, ccb->csio.cdb_len);
2535 	req->header.type = IOP_REQUEST_TYPE_SCSI_COMMAND;
2536 	req->header.result = IOP_RESULT_PENDING;
2537 	req->dataxfer_length = ccb->csio.dxfer_len;
2538 	req->channel = 0;
2539 	req->target =  ccb->ccb_h.target_id;
2540 	req->lun =  ccb->ccb_h.target_lun;
2541 	req->header.size = sizeof(struct hpt_iop_request_scsi_command)
2542 				- sizeof(struct hpt_iopsg)
2543 				+ nsegs * sizeof(struct hpt_iopsg);
2544 	if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
2545 		bus_dmamap_sync(hba->io_dmat,
2546 			srb->dma_map, BUS_DMASYNC_PREREAD);
2547 	}
2548 	else if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT)
2549 		bus_dmamap_sync(hba->io_dmat,
2550 			srb->dma_map, BUS_DMASYNC_PREWRITE);
2551 	req->header.context = (u_int64_t)srb->index
2552 					<< MVIOP_REQUEST_NUMBER_START_BIT
2553 					| MVIOP_CMD_TYPE_SCSI;
2554 	req->header.flags = IOP_REQUEST_FLAG_OUTPUT_CONTEXT;
2555 	size = req->header.size >> 8;
2556 	hptiop_mv_inbound_write(req_phy
2557 			| MVIOP_MU_QUEUE_ADDR_HOST_BIT
2558 			| imin(3, size), hba);
2559 }
2560 
2561 static void hptiop_post_req_mvfrey(struct hpt_iop_hba *hba,
2562 				struct hpt_iop_srb *srb,
2563 				bus_dma_segment_t *segs, int nsegs)
2564 {
2565 	int idx, index;
2566 	union ccb *ccb = srb->ccb;
2567 	u_int8_t *cdb;
2568 	struct hpt_iop_request_scsi_command *req;
2569 	u_int64_t req_phy;
2570 
2571 	req = (struct hpt_iop_request_scsi_command *)srb;
2572 	req_phy = srb->phy_addr;
2573 
2574 	if (ccb->csio.dxfer_len && nsegs > 0) {
2575 		struct hpt_iopsg *psg = req->sg_list;
2576 		for (idx = 0; idx < nsegs; idx++, psg++) {
2577 			psg->pci_address = (u_int64_t)segs[idx].ds_addr | 1;
2578 			psg->size = segs[idx].ds_len;
2579 			psg->eot = 0;
2580 		}
2581 		psg[-1].eot = 1;
2582 	}
2583 	if (ccb->ccb_h.flags & CAM_CDB_POINTER)
2584 		cdb = ccb->csio.cdb_io.cdb_ptr;
2585 	else
2586 		cdb = ccb->csio.cdb_io.cdb_bytes;
2587 
2588 	bcopy(cdb, req->cdb, ccb->csio.cdb_len);
2589 	req->header.type = IOP_REQUEST_TYPE_SCSI_COMMAND;
2590 	req->header.result = IOP_RESULT_PENDING;
2591 	req->dataxfer_length = ccb->csio.dxfer_len;
2592 	req->channel = 0;
2593 	req->target = ccb->ccb_h.target_id;
2594 	req->lun = ccb->ccb_h.target_lun;
2595 	req->header.size = sizeof(struct hpt_iop_request_scsi_command)
2596 				- sizeof(struct hpt_iopsg)
2597 				+ nsegs * sizeof(struct hpt_iopsg);
2598 	if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
2599 		bus_dmamap_sync(hba->io_dmat,
2600 			srb->dma_map, BUS_DMASYNC_PREREAD);
2601 	}
2602 	else if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT)
2603 		bus_dmamap_sync(hba->io_dmat,
2604 			srb->dma_map, BUS_DMASYNC_PREWRITE);
2605 
2606 	req->header.flags = IOP_REQUEST_FLAG_OUTPUT_CONTEXT
2607 						| IOP_REQUEST_FLAG_ADDR_BITS
2608 						| ((req_phy >> 16) & 0xffff0000);
2609 	req->header.context = ((req_phy & 0xffffffff) << 32 )
2610 						| srb->index << 4
2611 						| IOPMU_QUEUE_ADDR_HOST_BIT | req->header.type;
2612 
2613 	hba->u.mvfrey.inlist_wptr++;
2614 	index = hba->u.mvfrey.inlist_wptr & 0x3fff;
2615 
2616 	if (index == hba->u.mvfrey.list_count) {
2617 		index = 0;
2618 		hba->u.mvfrey.inlist_wptr &= ~0x3fff;
2619 		hba->u.mvfrey.inlist_wptr ^= CL_POINTER_TOGGLE;
2620 	}
2621 
2622 	hba->u.mvfrey.inlist[index].addr = req_phy;
2623 	hba->u.mvfrey.inlist[index].intrfc_len = (req->header.size + 3) / 4;
2624 
2625 	BUS_SPACE_WRT4_MVFREY2(inbound_write_ptr, hba->u.mvfrey.inlist_wptr);
2626 	BUS_SPACE_RD4_MVFREY2(inbound_write_ptr);
2627 
2628 	if (req->header.type == IOP_REQUEST_TYPE_SCSI_COMMAND) {
2629 		callout_reset(&srb->timeout, 20 * hz, hptiop_reset_adapter, hba);
2630 	}
2631 }
2632 
2633 static void hptiop_post_scsi_command(void *arg, bus_dma_segment_t *segs,
2634 					int nsegs, int error)
2635 {
2636 	struct hpt_iop_srb *srb = (struct hpt_iop_srb *)arg;
2637 	union ccb *ccb = srb->ccb;
2638 	struct hpt_iop_hba *hba = srb->hba;
2639 
2640 	if (error || nsegs > hba->max_sg_count) {
2641 		KdPrint(("hptiop: func_code=%x tid=%x lun=%jx nsegs=%d\n",
2642 			ccb->ccb_h.func_code,
2643 			ccb->ccb_h.target_id,
2644 			(uintmax_t)ccb->ccb_h.target_lun, nsegs));
2645 		ccb->ccb_h.status = CAM_BUSY;
2646 		bus_dmamap_unload(hba->io_dmat, srb->dma_map);
2647 		hptiop_free_srb(hba, srb);
2648 		xpt_done(ccb);
2649 		return;
2650 	}
2651 
2652 	hba->ops->post_req(hba, srb, segs, nsegs);
2653 }
2654 
2655 static void hptiop_mv_map_ctlcfg(void *arg, bus_dma_segment_t *segs,
2656 				int nsegs, int error)
2657 {
2658 	struct hpt_iop_hba *hba = (struct hpt_iop_hba *)arg;
2659 	hba->ctlcfgcmd_phy = ((u_int64_t)segs->ds_addr + 0x1F)
2660 				& ~(u_int64_t)0x1F;
2661 	hba->ctlcfg_ptr = (u_int8_t *)(((unsigned long)hba->ctlcfg_ptr + 0x1F)
2662 				& ~0x1F);
2663 }
2664 
2665 static void hptiop_mvfrey_map_ctlcfg(void *arg, bus_dma_segment_t *segs,
2666 				int nsegs, int error)
2667 {
2668 	struct hpt_iop_hba *hba = (struct hpt_iop_hba *)arg;
2669 	char *p;
2670 	u_int64_t phy;
2671 	u_int32_t list_count = hba->u.mvfrey.list_count;
2672 
2673 	phy = ((u_int64_t)segs->ds_addr + 0x1F)
2674 				& ~(u_int64_t)0x1F;
2675 	p = (u_int8_t *)(((unsigned long)hba->ctlcfg_ptr + 0x1F)
2676 				& ~0x1F);
2677 
2678 	hba->ctlcfgcmd_phy = phy;
2679 	hba->ctlcfg_ptr = p;
2680 
2681 	p += 0x800;
2682 	phy += 0x800;
2683 
2684 	hba->u.mvfrey.inlist = (struct mvfrey_inlist_entry *)p;
2685 	hba->u.mvfrey.inlist_phy = phy;
2686 
2687 	p += list_count * sizeof(struct mvfrey_inlist_entry);
2688 	phy += list_count * sizeof(struct mvfrey_inlist_entry);
2689 
2690 	hba->u.mvfrey.outlist = (struct mvfrey_outlist_entry *)p;
2691 	hba->u.mvfrey.outlist_phy = phy;
2692 
2693 	p += list_count * sizeof(struct mvfrey_outlist_entry);
2694 	phy += list_count * sizeof(struct mvfrey_outlist_entry);
2695 
2696 	hba->u.mvfrey.outlist_cptr = (u_int32_t *)p;
2697 	hba->u.mvfrey.outlist_cptr_phy = phy;
2698 }
2699 
2700 static void hptiop_map_srb(void *arg, bus_dma_segment_t *segs,
2701 				int nsegs, int error)
2702 {
2703 	struct hpt_iop_hba * hba = (struct hpt_iop_hba *)arg;
2704 	bus_addr_t phy_addr = (segs->ds_addr + 0x1F) & ~(bus_addr_t)0x1F;
2705 	struct hpt_iop_srb *srb, *tmp_srb;
2706 	int i;
2707 
2708 	if (error || nsegs == 0) {
2709 		device_printf(hba->pcidev, "hptiop_map_srb error");
2710 		return;
2711 	}
2712 
2713 	/* map srb */
2714 	srb = (struct hpt_iop_srb *)
2715 		(((unsigned long)hba->uncached_ptr + 0x1F)
2716 		& ~(unsigned long)0x1F);
2717 
2718 	for (i = 0; i < HPT_SRB_MAX_QUEUE_SIZE; i++) {
2719 		tmp_srb = (struct hpt_iop_srb *)
2720 					((char *)srb + i * HPT_SRB_MAX_SIZE);
2721 		if (((unsigned long)tmp_srb & 0x1F) == 0) {
2722 			if (bus_dmamap_create(hba->io_dmat,
2723 						0, &tmp_srb->dma_map)) {
2724 				device_printf(hba->pcidev, "dmamap create failed");
2725 				return;
2726 			}
2727 
2728 			bzero(tmp_srb, sizeof(struct hpt_iop_srb));
2729 			tmp_srb->hba = hba;
2730 			tmp_srb->index = i;
2731 			if (hba->ctlcfg_ptr == 0) {/*itl iop*/
2732 				tmp_srb->phy_addr = (u_int64_t)(u_int32_t)
2733 							(phy_addr >> 5);
2734 				if (phy_addr & IOPMU_MAX_MEM_SUPPORT_MASK_32G)
2735 					tmp_srb->srb_flag =
2736 						HPT_SRB_FLAG_HIGH_MEM_ACESS;
2737 			} else {
2738 				tmp_srb->phy_addr = phy_addr;
2739 			}
2740 
2741 			callout_init_mtx(&tmp_srb->timeout, &hba->lock, 0);
2742 			hptiop_free_srb(hba, tmp_srb);
2743 			hba->srb[i] = tmp_srb;
2744 			phy_addr += HPT_SRB_MAX_SIZE;
2745 		}
2746 		else {
2747 			device_printf(hba->pcidev, "invalid alignment");
2748 			return;
2749 		}
2750 	}
2751 }
2752 
2753 static void hptiop_os_message_callback(struct hpt_iop_hba * hba, u_int32_t msg)
2754 {
2755 	hba->msg_done = 1;
2756 }
2757 
2758 static  int hptiop_os_query_remove_device(struct hpt_iop_hba * hba,
2759 						int target_id)
2760 {
2761 	struct cam_periph       *periph = NULL;
2762 	struct cam_path         *path;
2763 	int                     status, retval = 0;
2764 
2765 	status = xpt_create_path(&path, NULL, hba->sim->path_id, target_id, 0);
2766 
2767 	if (status == CAM_REQ_CMP) {
2768 		if ((periph = cam_periph_find(path, "da")) != NULL) {
2769 			if (periph->refcount >= 1) {
2770 				device_printf(hba->pcidev, "%d ,"
2771 					"target_id=0x%x,"
2772 					"refcount=%d",
2773 				    hba->pciunit, target_id, periph->refcount);
2774 				retval = -1;
2775 			}
2776 		}
2777 		xpt_free_path(path);
2778 	}
2779 	return retval;
2780 }
2781 
2782 static void hptiop_release_resource(struct hpt_iop_hba *hba)
2783 {
2784 	int i;
2785 
2786 	if (hba->ioctl_dev)
2787 		destroy_dev(hba->ioctl_dev);
2788 
2789 	if (hba->path) {
2790 		struct ccb_setasync ccb;
2791 
2792 		memset(&ccb, 0, sizeof(ccb));
2793 		xpt_setup_ccb(&ccb.ccb_h, hba->path, /*priority*/5);
2794 		ccb.ccb_h.func_code = XPT_SASYNC_CB;
2795 		ccb.event_enable = 0;
2796 		ccb.callback = hptiop_async;
2797 		ccb.callback_arg = hba->sim;
2798 		xpt_action((union ccb *)&ccb);
2799 		xpt_free_path(hba->path);
2800 	}
2801 
2802 	if (hba->irq_handle)
2803 		bus_teardown_intr(hba->pcidev, hba->irq_res, hba->irq_handle);
2804 
2805 	if (hba->sim) {
2806 		hptiop_lock_adapter(hba);
2807 		xpt_bus_deregister(cam_sim_path(hba->sim));
2808 		cam_sim_free(hba->sim, TRUE);
2809 		hptiop_unlock_adapter(hba);
2810 	}
2811 
2812 	if (hba->ctlcfg_dmat) {
2813 		bus_dmamap_unload(hba->ctlcfg_dmat, hba->ctlcfg_dmamap);
2814 		bus_dmamem_free(hba->ctlcfg_dmat,
2815 					hba->ctlcfg_ptr, hba->ctlcfg_dmamap);
2816 		bus_dma_tag_destroy(hba->ctlcfg_dmat);
2817 	}
2818 
2819 	for (i = 0; i < HPT_SRB_MAX_QUEUE_SIZE; i++) {
2820 		struct hpt_iop_srb *srb = hba->srb[i];
2821 		if (srb->dma_map)
2822 			bus_dmamap_destroy(hba->io_dmat, srb->dma_map);
2823 		callout_drain(&srb->timeout);
2824 	}
2825 
2826 	if (hba->srb_dmat) {
2827 		bus_dmamap_unload(hba->srb_dmat, hba->srb_dmamap);
2828 		bus_dmamap_destroy(hba->srb_dmat, hba->srb_dmamap);
2829 		bus_dma_tag_destroy(hba->srb_dmat);
2830 	}
2831 
2832 	if (hba->io_dmat)
2833 		bus_dma_tag_destroy(hba->io_dmat);
2834 
2835 	if (hba->parent_dmat)
2836 		bus_dma_tag_destroy(hba->parent_dmat);
2837 
2838 	if (hba->irq_res)
2839 		bus_release_resource(hba->pcidev, SYS_RES_IRQ,
2840 					0, hba->irq_res);
2841 
2842 	if (hba->bar0_res)
2843 		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
2844 					hba->bar0_rid, hba->bar0_res);
2845 	if (hba->bar2_res)
2846 		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
2847 					hba->bar2_rid, hba->bar2_res);
2848 	mtx_destroy(&hba->lock);
2849 }
2850