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