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