xref: /freebsd/sys/dev/hptiop/hptiop.c (revision 1e413cf93298b5b97441a21d9a50fdcd0ee9945e)
1 /*
2  * HighPoint RR3xxx RAID Driver for FreeBSD
3  * Copyright (C) 2005-2007 HighPoint Technologies, Inc. All Rights Reserved.
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  */
25 
26 #include <sys/cdefs.h>
27 __FBSDID("$FreeBSD$");
28 
29 #include <sys/param.h>
30 #include <sys/types.h>
31 #include <sys/cons.h>
32 #if (__FreeBSD_version >= 500000)
33 #include <sys/time.h>
34 #include <sys/systm.h>
35 #else
36 #include <machine/clock.h>
37 #endif
38 
39 #include <sys/stat.h>
40 #include <sys/malloc.h>
41 #include <sys/conf.h>
42 #include <sys/libkern.h>
43 #include <sys/kernel.h>
44 
45 #if (__FreeBSD_version >= 500000)
46 #include <sys/kthread.h>
47 #include <sys/mutex.h>
48 #include <sys/module.h>
49 #endif
50 
51 #include <sys/eventhandler.h>
52 #include <sys/bus.h>
53 #include <sys/taskqueue.h>
54 #include <sys/ioccom.h>
55 
56 #include <machine/resource.h>
57 #include <machine/bus.h>
58 #include <machine/stdarg.h>
59 #include <sys/rman.h>
60 
61 #include <vm/vm.h>
62 #include <vm/pmap.h>
63 
64 #if (__FreeBSD_version >= 500000)
65 #include <dev/pci/pcireg.h>
66 #include <dev/pci/pcivar.h>
67 #else
68 #include <pci/pcivar.h>
69 #include <pci/pcireg.h>
70 #endif
71 
72 #if (__FreeBSD_version <= 500043)
73 #include <sys/devicestat.h>
74 #endif
75 
76 #include <cam/cam.h>
77 #include <cam/cam_ccb.h>
78 #include <cam/cam_sim.h>
79 #include <cam/cam_xpt_sim.h>
80 #include <cam/cam_debug.h>
81 #include <cam/cam_xpt_periph.h>
82 #include <cam/cam_periph.h>
83 #include <cam/scsi/scsi_all.h>
84 #include <cam/scsi/scsi_message.h>
85 
86 #if (__FreeBSD_version < 500043)
87 #include <sys/bus_private.h>
88 #endif
89 
90 #include <dev/hptiop/hptiop.h>
91 
92 static struct hpt_iop_hba * g_hba[4];
93 static int  iop_count = 0;
94 static char driver_name[] = "hptiop";
95 static char driver_version[] = "v1.2 (041307)";
96 static int  osm_max_targets = 32;
97 
98 static devclass_t hptiop_devclass;
99 
100 static void os_request_callback(struct hpt_iop_hba * hba, u_int32_t req);
101 static void os_message_callback(struct hpt_iop_hba * hba, u_int32_t msg);
102 static int  hptiop_do_ioctl(struct hpt_iop_hba * hba, struct hpt_iop_ioctl_param * pParams);
103 static void hptiop_bus_scan_cb(struct cam_periph *periph, union ccb *ccb);
104 static int  hptiop_rescan_bus(struct hpt_iop_hba * hba);
105 static int  hptiop_post_ioctl_command(struct hpt_iop_hba * hba,
106 		struct hpt_iop_request_ioctl_command * req, struct hpt_iop_ioctl_param * pParams);
107 static int  os_query_remove_device(struct hpt_iop_hba * hba, int target_id);
108 static int  hptiop_probe(device_t dev);
109 static int  hptiop_attach(device_t dev);
110 static int  hptiop_detach(device_t dev);
111 static int  hptiop_shutdown(device_t dev);
112 static void hptiop_action(struct cam_sim *sim, union ccb *ccb);
113 static void hptiop_poll(struct cam_sim *sim);
114 static void hptiop_async(void * callback_arg, u_int32_t code,
115 					struct cam_path * path, void * arg);
116 static void hptiop_pci_intr(void *arg);
117 static void hptiop_release_resource(struct hpt_iop_hba * hba);
118 static int  hptiop_reset_adapter(struct hpt_iop_hba * hba);
119 static void hptiop_enable_interrupts(struct hpt_iop_hba * hba);
120 static void hptiop_disable_interrupts(struct hpt_iop_hba * hba);
121 
122 static d_open_t hptiop_open;
123 static d_close_t hptiop_close;
124 static d_ioctl_t hptiop_ioctl;
125 
126 static struct cdevsw hptiop_cdevsw = {
127 	.d_open = hptiop_open,
128 	.d_close = hptiop_close,
129 	.d_ioctl = hptiop_ioctl,
130 	.d_name = driver_name,
131 #if __FreeBSD_version>=503000
132 	.d_version = D_VERSION,
133 #endif
134 #if (__FreeBSD_version>=503000 && __FreeBSD_version<600034)
135 	.d_flags = D_NEEDGIANT,
136 #endif
137 #if __FreeBSD_version<600034
138 #if __FreeBSD_version>=501000
139 	.d_maj = MAJOR_AUTO,
140 #else
141 	.d_maj = HPT_DEV_MAJOR,
142 #endif
143 #endif
144 };
145 
146 #if __FreeBSD_version < 503000
147 #define hba_from_dev(dev) ((struct hpt_iop_hba *)(dev)->si_drv1)
148 #else
149 #define hba_from_dev(dev) \
150 		((struct hpt_iop_hba *)devclass_get_softc(hptiop_devclass, minor(dev)))
151 #endif
152 
153 static int hptiop_open(ioctl_dev_t dev, int flags,
154 					int devtype, ioctl_thread_t proc)
155 {
156 	struct hpt_iop_hba * hba = hba_from_dev(dev);
157 
158 	if (hba==NULL)
159 		return ENXIO;
160 	if (hba->flag & HPT_IOCTL_FLAG_OPEN)
161 		return EBUSY;
162 	hba->flag |= HPT_IOCTL_FLAG_OPEN;
163 	return 0;
164 }
165 
166 static int hptiop_close(ioctl_dev_t dev, int flags,
167 					int devtype, ioctl_thread_t proc)
168 {
169 	struct hpt_iop_hba * hba = hba_from_dev(dev);
170 	hba->flag &= ~(u_int32_t)HPT_IOCTL_FLAG_OPEN;
171 	return 0;
172 }
173 
174 static int hptiop_ioctl(ioctl_dev_t dev, u_long cmd, caddr_t data,
175 					int flags, ioctl_thread_t proc)
176 {
177 	int ret = EFAULT;
178 	struct hpt_iop_hba * hba = hba_from_dev(dev);
179 
180 #if (__FreeBSD_version >= 500000)
181 	mtx_lock(&Giant);
182 #endif
183 
184 	switch (cmd) {
185 	case HPT_DO_IOCONTROL:
186 		ret = hptiop_do_ioctl(hba, (struct hpt_iop_ioctl_param *)data);
187 		break;
188 	case HPT_SCAN_BUS:
189 		ret = hptiop_rescan_bus(hba);
190 		break;
191 	}
192 
193 #if (__FreeBSD_version >= 500000)
194 	mtx_unlock(&Giant);
195 #endif
196 
197 	return ret;
198 }
199 
200 static __inline void * iop_get_inbound_request(struct hpt_iopmu * iop)
201 {
202 	u_int32_t m = readl(&iop->inbound_queue);
203 	return (m == 0xFFFFFFFF)? 0 : ((char *)iop + m);
204 }
205 
206 static __inline void iop_post_inbound_request(struct hpt_iopmu * iop, void *req)
207 {
208 	writel(&iop->inbound_queue, (char *)req - (char *)iop);
209 }
210 
211 static __inline void iop_post_outbound_request(struct hpt_iopmu * iop, void *req)
212 {
213 	writel(&iop->outbound_queue, (char *)req - (char *)iop);
214 }
215 
216 static __inline void hptiop_pci_posting_flush(struct hpt_iopmu * iop)
217 {
218 	readl(&iop->outbound_intstatus);
219 }
220 
221 static int iop_wait_ready(struct hpt_iopmu * iop, u_int32_t millisec)
222 {
223 	u_int32_t req=0;
224 	int i;
225 
226 	for (i = 0; i < millisec; i++) {
227 		req = readl(&iop->inbound_queue);
228 		if (req != IOPMU_QUEUE_EMPTY)
229 			break;
230 		DELAY(1000);
231 	}
232 
233 	if (req!=IOPMU_QUEUE_EMPTY) {
234 		writel(&iop->outbound_queue, req);
235 		hptiop_pci_posting_flush(iop);
236 		return 0;
237 	}
238 
239 	return -1;
240 }
241 
242 static int iop_intr(struct hpt_iop_hba * hba)
243 {
244 	struct hpt_iopmu * iop = hba->iop;
245 	u_int32_t status;
246 	int ret = 0;
247 
248 	status = readl(&iop->outbound_intstatus);
249 
250 	if (status & IOPMU_OUTBOUND_INT_MSG0) {
251 		u_int32_t msg = readl(&iop->outbound_msgaddr0);
252 		KdPrint(("received outbound msg %x", msg));
253 		writel(&iop->outbound_intstatus, IOPMU_OUTBOUND_INT_MSG0);
254 		os_message_callback(hba, msg);
255 		ret = 1;
256 	}
257 
258 	if (status & IOPMU_OUTBOUND_INT_POSTQUEUE) {
259 		u_int32_t req;
260 		while ((req = readl(&iop->outbound_queue))
261 							!=IOPMU_QUEUE_EMPTY) {
262 			if (req & IOPMU_QUEUE_MASK_HOST_BITS)
263 				os_request_callback(hba, req);
264 			else {
265 				struct hpt_iop_request_header * p;
266 				p = (struct hpt_iop_request_header *)((char *)hba->iop + req);
267 				if (p->flags & IOP_REQUEST_FLAG_SYNC_REQUEST) {
268 					if (p->context)
269 						os_request_callback(hba, req);
270 					else
271 						p->context= 1;
272 				}
273 				else
274 					os_request_callback(hba, req);
275 			}
276 		}
277 		ret = 1;
278 	}
279 	return ret;
280 }
281 
282 static int iop_send_sync_request(struct hpt_iop_hba * hba, void *req, u_int32_t millisec)
283 {
284 	u_int32_t i;
285 
286 	((struct hpt_iop_request_header *)req)->flags |= IOP_REQUEST_FLAG_SYNC_REQUEST;
287 	((struct hpt_iop_request_header *)req)->context = 0;
288 
289 	writel(&hba->iop->inbound_queue,
290 			(u_int32_t)((char *)req - (char *)hba->iop));
291 
292 	hptiop_pci_posting_flush(hba->iop);
293 
294 	for (i = 0; i < millisec; i++) {
295 		iop_intr(hba);
296 		if (((struct hpt_iop_request_header *)req)->context)
297 			return 0;
298 		DELAY(1000);
299 	}
300 
301 	return -1;
302 }
303 
304 static int iop_send_sync_msg(struct hpt_iop_hba * hba, u_int32_t msg, int *done, u_int32_t millisec)
305 {
306 	u_int32_t i;
307 
308 	*done = 0;
309 
310 	writel(&hba->iop->inbound_msgaddr0, msg);
311 
312 	hptiop_pci_posting_flush(hba->iop);
313 
314 	for (i = 0; i < millisec; i++) {
315 		iop_intr(hba);
316 		if (*done)
317 			break;
318 		DELAY(1000);
319 	}
320 
321 	return *done? 0 : -1;
322 }
323 
324 static int iop_get_config(struct hpt_iop_hba * hba, struct hpt_iop_request_get_config * config)
325 {
326 	u_int32_t req32=0;
327 	struct hpt_iop_request_get_config * req;
328 
329 	if ((req32 = readl(&hba->iop->inbound_queue)) == IOPMU_QUEUE_EMPTY)
330 		return -1;
331 
332 	req = (struct hpt_iop_request_get_config *)((char *)hba->iop + req32);
333 	req->header.flags = 0;
334 	req->header.type = IOP_REQUEST_TYPE_GET_CONFIG;
335 	req->header.size = sizeof(struct hpt_iop_request_get_config);
336 	req->header.result = IOP_RESULT_PENDING;
337 
338 	if (iop_send_sync_request(hba, req, 20000)) {
339 		KdPrint(("Get config send cmd failed"));
340 		return -1;
341 	}
342 
343 	*config = *req;
344 	writel(&hba->iop->outbound_queue, req32);
345 	return 0;
346 }
347 
348 static int iop_set_config(struct hpt_iop_hba * hba, struct hpt_iop_request_set_config *config)
349 {
350 	u_int32_t req32;
351 	struct hpt_iop_request_set_config *req;
352 
353 	req32 = readl(&hba->iop->inbound_queue);
354 	if (req32 == IOPMU_QUEUE_EMPTY)
355 		return -1;
356 
357 	req = (struct hpt_iop_request_set_config *)((char *)hba->iop + req32);
358 	memcpy((u_int8_t *)req + sizeof(struct hpt_iop_request_header),
359 		(u_int8_t *)config + sizeof(struct hpt_iop_request_header),
360 		sizeof(struct hpt_iop_request_set_config) - sizeof(struct hpt_iop_request_header));
361 	req->header.flags = 0;
362 	req->header.type = IOP_REQUEST_TYPE_SET_CONFIG;
363 	req->header.size = sizeof(struct hpt_iop_request_set_config);
364 	req->header.result = IOP_RESULT_PENDING;
365 
366 	if (iop_send_sync_request(hba, req, 20000)) {
367 		KdPrint(("Set config send cmd failed"));
368 		return -1;
369 	}
370 
371 	writel(&hba->iop->outbound_queue, req32);
372 	return 0;
373 }
374 
375 static int hptiop_do_ioctl(struct hpt_iop_hba * hba, struct hpt_iop_ioctl_param * pParams)
376 {
377 	struct hpt_iop_request_ioctl_command * req;
378 
379 	if ((pParams->Magic != HPT_IOCTL_MAGIC) &&
380 		(pParams->Magic != HPT_IOCTL_MAGIC32))
381 		return EFAULT;
382 
383 	req = (struct hpt_iop_request_ioctl_command *)iop_get_inbound_request(hba->iop);
384 	if (!req) {
385 		printf("hptiop: ioctl command failed");
386 		return EFAULT;
387 	}
388 
389 	if (pParams->nInBufferSize)
390 		if (copyin((void *)pParams->lpInBuffer,
391 				req->buf, pParams->nInBufferSize))
392 			goto invalid;
393 
394 	if (hptiop_post_ioctl_command(hba, req, pParams))
395 		goto invalid;
396 
397 	if (req->header.result == IOP_RESULT_SUCCESS) {
398 		if (pParams->nOutBufferSize)
399 			if (copyout(req->buf +
400 					((pParams->nInBufferSize + 3) & ~3),
401 					(void*)pParams->lpOutBuffer,
402 					pParams->nOutBufferSize))
403 				goto invalid;
404 
405 		if (pParams->lpBytesReturned)
406 			if (copyout(&req->bytes_returned,
407 					(void*)pParams->lpBytesReturned,
408 					sizeof(u_int32_t)))
409 				goto invalid;
410 		iop_post_outbound_request(hba->iop, req);
411 		return 0;
412 	} else{
413 invalid:
414 		iop_post_outbound_request(hba->iop, req);
415 		return EFAULT;
416 	}
417 }
418 
419 static int hptiop_post_ioctl_command(struct hpt_iop_hba *hba,
420 		struct hpt_iop_request_ioctl_command *req, struct hpt_iop_ioctl_param *pParams)
421 {
422 	if (((pParams->nInBufferSize + 3) & ~3) + pParams->nOutBufferSize >
423 			hba->max_request_size - sizeof(struct hpt_iop_request_header) -
424 					4 * sizeof(u_int32_t)) {
425 		printf("hptiop: request size beyond max value");
426 		return -1;
427 	}
428 
429 	req->ioctl_code = HPT_CTL_CODE_BSD_TO_IOP(pParams->dwIoControlCode);
430 	req->inbuf_size = pParams->nInBufferSize;
431 	req->outbuf_size = pParams->nOutBufferSize;
432 
433 	req->header.size = sizeof(struct hpt_iop_request_ioctl_command)
434 					- 4 + pParams->nInBufferSize;
435 	req->header.context = (u_int64_t)(unsigned long)req;
436 	req->header.type = IOP_REQUEST_TYPE_IOCTL_COMMAND;
437 	req->header.result = IOP_RESULT_PENDING;
438 	req->header.flags |= IOP_REQUEST_FLAG_SYNC_REQUEST;
439 
440 	hptiop_lock_adapter(hba);
441 	iop_post_inbound_request(hba->iop, req);
442 	hptiop_pci_posting_flush(hba->iop);
443 
444 	while (req->header.context) {
445 		if (hptiop_sleep(hba, req,
446 				PPAUSE, "hptctl", HPT_OSM_TIMEOUT)==0)
447 			break;
448 		iop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_RESET,
449 						&hba->msg_done, 60000);
450 	}
451 
452 	hptiop_unlock_adapter(hba);
453 	return 0;
454 }
455 
456 static int  hptiop_rescan_bus(struct hpt_iop_hba * hba)
457 {
458 	struct cam_path     *path;
459 	union ccb           *ccb;
460 	if (xpt_create_path(&path, xpt_periph, cam_sim_path(hba->sim),
461 		CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP)
462 		return(EIO);
463 	if ((ccb = malloc(sizeof(union ccb), M_TEMP, M_WAITOK)) == NULL)
464 		return(ENOMEM);
465 	bzero(ccb, sizeof(union ccb));
466 	xpt_setup_ccb(&ccb->ccb_h, path, 5);
467 	ccb->ccb_h.func_code = XPT_SCAN_BUS;
468 	ccb->ccb_h.cbfcnp = hptiop_bus_scan_cb;
469 	ccb->crcn.flags = CAM_FLAG_NONE;
470 	xpt_action(ccb);
471 	return(0);
472 }
473 
474 static void hptiop_bus_scan_cb(struct cam_periph *periph, union ccb *ccb)
475 {
476 	xpt_free_path(ccb->ccb_h.path);
477 	free(ccb, M_TEMP);
478 	return;
479 }
480 
481 static  bus_dmamap_callback_t   hptiop_map_srb;
482 static  bus_dmamap_callback_t   hptiop_post_scsi_command;
483 
484 /*
485  * CAM driver interface
486  */
487 static device_method_t driver_methods[] = {
488 	/* Device interface */
489 	DEVMETHOD(device_probe,     hptiop_probe),
490 	DEVMETHOD(device_attach,    hptiop_attach),
491 	DEVMETHOD(device_detach,    hptiop_detach),
492 	DEVMETHOD(device_shutdown,  hptiop_shutdown),
493 	{ 0, 0 }
494 };
495 
496 static driver_t hptiop_pci_driver = {
497 	driver_name,
498 	driver_methods,
499 	sizeof(struct hpt_iop_hba)
500 };
501 
502 DRIVER_MODULE(hptiop, pci, hptiop_pci_driver, hptiop_devclass, 0, 0);
503 
504 static int hptiop_probe(device_t dev)
505 {
506 	struct hpt_iop_hba *hba;
507 
508 	if ((pci_get_vendor(dev) == 0x1103 && pci_get_device(dev) == 0x3220) ||
509 		(pci_get_vendor(dev) == 0x1103 && pci_get_device(dev) == 0x3320) ||
510 		(pci_get_vendor(dev) == 0x1103 && pci_get_device(dev) == 0x3520)) {
511 		printf("hptiop: adapter at PCI %d:%d:%d, IRQ %d",
512 			pci_get_bus(dev), pci_get_slot(dev),
513 			pci_get_function(dev), pci_get_irq(dev));
514 		device_set_desc(dev, driver_name);
515 		hba = (struct hpt_iop_hba *)device_get_softc(dev);
516 		memset(hba, 0, sizeof(struct hpt_iop_hba));
517 		return 0;
518 	}
519 	return ENXIO;
520 }
521 
522 static int hptiop_attach(device_t dev)
523 {
524 	struct hpt_iop_hba * hba = (struct hpt_iop_hba *)device_get_softc(dev);
525 	struct hpt_iop_request_get_config  iop_config;
526 	struct hpt_iop_request_set_config  set_config;
527 	int rid = 0;
528 	struct cam_devq *devq;
529 	struct ccb_setasync ccb;
530 	u_int32_t unit = device_get_unit(dev);
531 
532 	printf("%s%d: RocketRAID 3xxx controller driver %s\n",
533 		driver_name, unit, driver_version);
534 
535 	KdPrint(("hptiop_attach(%d, %d/%d/%d)", unit,
536 		pci_get_bus(dev), pci_get_slot(dev), pci_get_function(dev)));
537 
538 #if __FreeBSD_version >=440000
539 	pci_enable_busmaster(dev);
540 #endif
541 	hba->pcidev = dev;
542 	hba->pciunit = unit;
543 
544 	hba->bar0_rid = 0x10;
545 	hba->bar0_res = bus_alloc_resource(hba->pcidev,
546 					SYS_RES_MEMORY,	&hba->bar0_rid,
547 					0, ~0, 0x100000, RF_ACTIVE);
548 
549 	if (hba->bar0_res == NULL) {
550 		printf("hptiop: Failed to get iop base adrress.\n");
551 		return ENXIO;
552 	}
553 
554 	hba->iop = (struct hpt_iopmu *)rman_get_virtual(hba->bar0_res);
555 
556 	if (!hba->iop) {
557 		printf("hptiop: alloc mem res failed\n");
558 		return ENXIO;
559 	}
560 
561 	if (iop_wait_ready(hba->iop, 2000)) {
562 		printf("hptiop: adapter is not ready\n");
563 		return ENXIO;
564 	}
565 
566 	if (iop_get_config(hba, &iop_config)) {
567 		printf("hptiop: Get iop config failed.\n");
568 		return ENXIO;
569 	}
570 
571 	hba->firmware_version = iop_config.firmware_version;
572 	hba->interface_version = iop_config.interface_version;
573 	hba->max_requests = iop_config.max_requests;
574 	hba->max_devices = iop_config.max_devices;
575 	hba->max_request_size = iop_config.request_size;
576 	hba->max_sg_count = iop_config.max_sg_count;
577 
578 #if (__FreeBSD_version >= 500000)
579 	mtx_init(&hba->lock, "hptioplock", NULL, MTX_DEF);
580 #endif
581 
582 	if (bus_dma_tag_create(NULL,/* parent */
583 			1,  /* alignment */
584 			0, /* boundary */
585 			BUS_SPACE_MAXADDR,  /* lowaddr */
586 			BUS_SPACE_MAXADDR,  /* highaddr */
587 			NULL, NULL,         /* filter, filterarg */
588 			BUS_SPACE_MAXSIZE_32BIT,    /* maxsize */
589 			BUS_SPACE_UNRESTRICTED, /* nsegments */
590 			BUS_SPACE_MAXSIZE_32BIT,    /* maxsegsize */
591 			0,      /* flags */
592 #if __FreeBSD_version>502000
593 			NULL,   /* lockfunc */
594 			NULL,       /* lockfuncarg */
595 #endif
596 			&hba->parent_dmat   /* tag */))
597 	{
598 		printf("hptiop: alloc parent_dmat failed\n");
599 		return ENXIO;
600 	}
601 
602 	if (bus_dma_tag_create(hba->parent_dmat,/* parent */
603 			4,  /* alignment */
604 			BUS_SPACE_MAXADDR_32BIT+1, /* boundary */
605 			BUS_SPACE_MAXADDR,  /* lowaddr */
606 			BUS_SPACE_MAXADDR,  /* highaddr */
607 			NULL, NULL,         /* filter, filterarg */
608 			PAGE_SIZE * (hba->max_sg_count-1),  /* maxsize */
609 			hba->max_sg_count,  /* nsegments */
610 			0x20000,    /* maxsegsize */
611 			BUS_DMA_ALLOCNOW,       /* flags */
612 #if __FreeBSD_version>502000
613 			busdma_lock_mutex,  /* lockfunc */
614 			&hba->lock,     /* lockfuncarg */
615 #endif
616 			&hba->io_dmat   /* tag */))
617 	{
618 		printf("hptiop: alloc io_dmat failed\n");
619 		bus_dma_tag_destroy(hba->parent_dmat);
620 		return ENXIO;
621 	}
622 
623 	if (bus_dma_tag_create(hba->parent_dmat,/* parent */
624 			1,  /* alignment */
625 			0, /* boundary */
626 			BUS_SPACE_MAXADDR_32BIT,    /* lowaddr */
627 			BUS_SPACE_MAXADDR,  /* highaddr */
628 			NULL, NULL,         /* filter, filterarg */
629 			HPT_SRB_MAX_SIZE * HPT_SRB_MAX_QUEUE_SIZE + 0x20,
630 			1,  /* nsegments */
631 			BUS_SPACE_MAXSIZE_32BIT,    /* maxsegsize */
632 			0,      /* flags */
633 #if __FreeBSD_version>502000
634 			NULL,   /* lockfunc */
635 			NULL,       /* lockfuncarg */
636 #endif
637 			&hba->srb_dmat  /* tag */))
638 	{
639 		printf("hptiop: alloc srb_dmat failed\n");
640 		bus_dma_tag_destroy(hba->io_dmat);
641 		bus_dma_tag_destroy(hba->parent_dmat);
642 		return ENXIO;
643 	}
644 
645 	if (bus_dmamem_alloc(hba->srb_dmat, (void **)&hba->uncached_ptr,
646 #if __FreeBSD_version>501000
647 		BUS_DMA_WAITOK | BUS_DMA_COHERENT,
648 #else
649 		BUS_DMA_WAITOK,
650 #endif
651 		&hba->srb_dmamap) != 0)
652 	{
653 			printf("hptiop: bus_dmamem_alloc failed!\n");
654 release_tag:
655 			bus_dma_tag_destroy(hba->srb_dmat);
656 			bus_dma_tag_destroy(hba->io_dmat);
657 			bus_dma_tag_destroy(hba->parent_dmat);
658 			return ENXIO;
659 	}
660 
661 	if (bus_dmamap_load(hba->srb_dmat,
662 			hba->srb_dmamap, hba->uncached_ptr,
663 			(HPT_SRB_MAX_SIZE * HPT_SRB_MAX_QUEUE_SIZE) + 0x20,
664 			hptiop_map_srb, hba, 0))
665 	{
666 		printf("hptiop: bus_dmamap_load failed!\n");
667 		goto release_tag;
668 	}
669 
670 	if ((devq = cam_simq_alloc(hba->max_requests - 1 )) == NULL) {
671 		printf("hptiop: cam_simq_alloc failed\n");
672 attach_failed:
673 		hptiop_release_resource(hba);
674 		return ENXIO;
675 	}
676 	hba->sim = cam_sim_alloc(hptiop_action, hptiop_poll, driver_name,
677 			hba, unit, &Giant, hba->max_requests - 1, 1, devq);
678 	if (!hba->sim) {
679 		printf("hptiop: cam_sim_alloc failed\n");
680 		cam_simq_free(devq);
681 		goto attach_failed;
682 	}
683 
684 	if (xpt_bus_register(hba->sim, dev, 0) != CAM_SUCCESS) {
685 		printf("hptiop: xpt_bus_register failed\n");
686 		cam_sim_free(hba->sim, /*free devq*/ TRUE);
687 		hba->sim = NULL;
688 		goto attach_failed;
689 	}
690 
691 	if (xpt_create_path(&hba->path, /*periph */ NULL,
692 			cam_sim_path(hba->sim), CAM_TARGET_WILDCARD,
693 			CAM_LUN_WILDCARD) != CAM_REQ_CMP)
694 	{
695 		printf("hptiop: xpt_create_path failed\n");
696 		xpt_bus_deregister(cam_sim_path(hba->sim));
697 		cam_sim_free(hba->sim, /*free_devq*/TRUE);
698 		hba->sim = NULL;
699 		goto attach_failed;
700 	}
701 
702 	bzero(&set_config, sizeof(set_config));
703 	set_config.iop_id = iop_count;
704 	set_config.vbus_id = cam_sim_path(hba->sim);
705 	set_config.max_host_request_size = HPT_SRB_MAX_REQ_SIZE;
706 
707 	if (iop_set_config(hba, &set_config)) {
708 		printf("hptiop: Set iop config failed.\n");
709 		goto attach_failed;
710 	}
711 
712 	xpt_setup_ccb(&ccb.ccb_h, hba->path, /*priority*/5);
713 	ccb.ccb_h.func_code = XPT_SASYNC_CB;
714 	ccb.event_enable = (AC_FOUND_DEVICE | AC_LOST_DEVICE);
715 	ccb.callback = hptiop_async;
716 	ccb.callback_arg = hba->sim;
717 	xpt_action((union ccb *)&ccb);
718 
719 	rid = 0;
720 	if ((hba->irq_res = bus_alloc_resource(hba->pcidev, SYS_RES_IRQ,
721 			&rid, 0, ~0ul, 1, RF_SHAREABLE | RF_ACTIVE)) == NULL) {
722 		printf("hptiop: allocate irq failed!\n");
723 		goto attach_failed;
724 	}
725 
726 	if (bus_setup_intr(hba->pcidev, hba->irq_res, INTR_TYPE_CAM,
727 				NULL, hptiop_pci_intr, hba, &hba->irq_handle)) {
728 		printf("hptiop: allocate intr function failed!\n");
729 		goto attach_failed;
730 	}
731 
732 	hptiop_enable_interrupts(hba);
733 
734 	if (iop_send_sync_msg(hba,
735 			IOPMU_INBOUND_MSG0_START_BACKGROUND_TASK,
736 			&hba->msg_done, 5000)) {
737 		printf("hptiop: Fail to start background task\n");
738 		goto attach_failed;
739 	}
740 
741 	hba->ioctl_dev = make_dev(&hptiop_cdevsw, unit,
742 				UID_ROOT, GID_WHEEL /*GID_OPERATOR*/,
743 				S_IRUSR | S_IWUSR, "%s%d", driver_name, unit);
744 
745 #if __FreeBSD_version < 503000
746 	hba->ioctl_dev->si_drv1 = hba;
747 #endif
748 
749 	hptiop_rescan_bus(hba);
750 
751 	g_hba[iop_count++] = hba;
752 	return 0;
753 }
754 
755 static int hptiop_detach(device_t dev)
756 {
757 	struct hpt_iop_hba * hba = (struct hpt_iop_hba *)device_get_softc(dev);
758 	int i;
759 	int error = EBUSY;
760 
761 	hptiop_lock_adapter(hba);
762 	for (i = 0; i < osm_max_targets; i++)
763 		if (os_query_remove_device(hba, i)) {
764 			printf("hptiop%d file system is busy. id=%d",
765 						hba->pciunit, i);
766 			goto out;
767 		}
768 
769 	if ((error = hptiop_shutdown(dev)) != 0)
770 		goto out;
771 	if (iop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_STOP_BACKGROUND_TASK,
772 						&hba->msg_done, 60000))
773 		goto out;
774 
775 	hptiop_release_resource(hba);
776 	error = 0;
777 out:
778 	hptiop_unlock_adapter(hba);
779 	return error;
780 }
781 
782 static int hptiop_shutdown(device_t dev)
783 {
784 	struct hpt_iop_hba * hba = (struct hpt_iop_hba *)device_get_softc(dev);
785 
786 	int error = 0;
787 
788 	if (hba->flag & HPT_IOCTL_FLAG_OPEN) {
789 		printf("hptiop: %d server is busy", hba->pciunit);
790 		return EBUSY;
791 	}
792 	hptiop_disable_interrupts(hba);
793 	if (iop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_SHUTDOWN,
794 						&hba->msg_done, 60000))
795 		error = EBUSY;
796 
797 	return error;
798 }
799 
800 static void hptiop_pci_intr(void *arg)
801 {
802 	struct hpt_iop_hba * hba = (struct hpt_iop_hba *)arg;
803 	hptiop_lock_adapter(hba);
804 	iop_intr(hba);
805 	hptiop_unlock_adapter(hba);
806 }
807 
808 static void hptiop_poll(struct cam_sim *sim)
809 {
810 	hptiop_pci_intr(cam_sim_softc(sim));
811 }
812 
813 static void hptiop_async(void * callback_arg, u_int32_t code,
814 					struct cam_path * path, void * arg)
815 {
816 }
817 
818 static void hptiop_enable_interrupts(struct hpt_iop_hba * hba)
819 {
820 	writel(&hba->iop->outbound_intmask,
821 		~(IOPMU_OUTBOUND_INT_POSTQUEUE | IOPMU_OUTBOUND_INT_MSG0));
822 }
823 
824 static void hptiop_disable_interrupts(struct hpt_iop_hba * hba)
825 {
826 	u_int32_t int_mask;
827 
828 	int_mask = readl(&hba->iop->outbound_intmask);
829 	writel(&hba->iop->outbound_intmask, int_mask |
830 		IOPMU_OUTBOUND_INT_POSTQUEUE | IOPMU_OUTBOUND_INT_MSG0);
831 	hptiop_pci_posting_flush(hba->iop);
832 }
833 
834 static int hptiop_reset_adapter(struct hpt_iop_hba * hba)
835 {
836 	return iop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_RESET,
837 						&hba->msg_done, 60000);
838 }
839 
840 static void *hptiop_get_srb(struct hpt_iop_hba * hba)
841 {
842 	struct hpt_iop_srb * srb;
843 
844 	if (hba->srb_list) {
845 		srb = hba->srb_list;
846 		hba->srb_list = srb->next;
847 	}
848 	else
849 		srb=NULL;
850 
851 	return srb;
852 }
853 
854 static void hptiop_free_srb(struct hpt_iop_hba * hba, struct hpt_iop_srb * srb)
855 {
856 	srb->next = hba->srb_list;
857 	hba->srb_list = srb;
858 }
859 
860 static void hptiop_action(struct cam_sim *sim, union ccb *ccb)
861 {
862 	struct hpt_iop_hba * hba = (struct hpt_iop_hba *)cam_sim_softc(sim);
863 	struct hpt_iop_srb * srb;
864 
865 	switch (ccb->ccb_h.func_code) {
866 
867 	case XPT_SCSI_IO:
868 		hptiop_lock_adapter(hba);
869 		if (ccb->ccb_h.target_lun != 0 ||
870 			ccb->ccb_h.target_id >= osm_max_targets ||
871 			(ccb->ccb_h.flags & CAM_CDB_PHYS))
872 		{
873 			ccb->ccb_h.status = CAM_TID_INVALID;
874 			xpt_done(ccb);
875 			goto scsi_done;
876 		}
877 
878 		if ((srb = hptiop_get_srb(hba)) == NULL) {
879 			printf("hptiop: srb allocated failed");
880 			ccb->ccb_h.status = CAM_REQ_CMP_ERR;
881 			xpt_done(ccb);
882 			goto scsi_done;
883 		}
884 
885 		srb->ccb = ccb;
886 
887 		if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_NONE)
888 			hptiop_post_scsi_command(srb, NULL, 0, 0);
889 		else if ((ccb->ccb_h.flags & CAM_SCATTER_VALID) == 0) {
890 			if ((ccb->ccb_h.flags & CAM_DATA_PHYS) == 0) {
891 				int error;
892 
893 				error = bus_dmamap_load(hba->io_dmat,
894 					srb->dma_map,
895 					ccb->csio.data_ptr, ccb->csio.dxfer_len,
896 					hptiop_post_scsi_command, srb, 0);
897 
898 				if (error && error != EINPROGRESS) {
899 					printf("hptiop: %d bus_dmamap_load error %d",
900 							hba->pciunit, error);
901 					xpt_freeze_simq(hba->sim, 1);
902 					ccb->ccb_h.status = CAM_REQ_CMP_ERR;
903 invalid:
904 					hptiop_free_srb(hba, srb);
905 					xpt_done(ccb);
906 					goto scsi_done;
907 				}
908 			}
909 			else {
910 				printf("hptiop: CAM_DATA_PHYS not supported");
911 				ccb->ccb_h.status = CAM_REQ_CMP_ERR;
912 				goto invalid;
913 			}
914 		}
915 		else {
916 			struct bus_dma_segment *segs;
917 
918 			if ((ccb->ccb_h.flags & CAM_SG_LIST_PHYS) == 0 ||
919 				(ccb->ccb_h.flags & CAM_DATA_PHYS) != 0) {
920 				printf("hptiop: SCSI cmd failed");
921 				ccb->ccb_h.status=CAM_PROVIDE_FAIL;
922 				goto invalid;
923 			}
924 
925 			segs = (struct bus_dma_segment *)ccb->csio.data_ptr;
926 			hptiop_post_scsi_command(srb, segs,
927 						ccb->csio.sglist_cnt, 0);
928 		}
929 
930 scsi_done:
931 		hptiop_unlock_adapter(hba);
932 		return;
933 
934 	case XPT_RESET_BUS:
935 		printf("hptiop: reset adapter");
936 		hptiop_lock_adapter(hba);
937 		hba->msg_done = 0;
938 		hptiop_reset_adapter(hba);
939 		hptiop_unlock_adapter(hba);
940 		break;
941 
942 	case XPT_GET_TRAN_SETTINGS:
943 	case XPT_SET_TRAN_SETTINGS:
944 		ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
945 		break;
946 
947 	case XPT_CALC_GEOMETRY:
948 		ccb->ccg.heads = 255;
949 		ccb->ccg.secs_per_track = 63;
950 		ccb->ccg.cylinders = ccb->ccg.volume_size /
951 				(ccb->ccg.heads * ccb->ccg.secs_per_track);
952 		ccb->ccb_h.status = CAM_REQ_CMP;
953 		break;
954 
955 	case XPT_PATH_INQ:
956 	{
957 		struct ccb_pathinq *cpi = &ccb->cpi;
958 
959 		cpi->version_num = 1;
960 		cpi->hba_inquiry = PI_SDTR_ABLE;
961 		cpi->target_sprt = 0;
962 		cpi->hba_misc = PIM_NOBUSRESET;
963 		cpi->hba_eng_cnt = 0;
964 		cpi->max_target = osm_max_targets;
965 		cpi->max_lun = 0;
966 		cpi->unit_number = cam_sim_unit(sim);
967 		cpi->bus_id = cam_sim_bus(sim);
968 		cpi->initiator_id = osm_max_targets;
969 		cpi->base_transfer_speed = 3300;
970 
971 		strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
972 		strncpy(cpi->hba_vid, "HPT   ", HBA_IDLEN);
973 		strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
974 		cpi->ccb_h.status = CAM_REQ_CMP;
975 		break;
976 	}
977 
978 	default:
979 		ccb->ccb_h.status = CAM_REQ_INVALID;
980 		break;
981 	}
982 
983 	xpt_done(ccb);
984 	return;
985 }
986 
987 static void hptiop_post_scsi_command(void *arg, bus_dma_segment_t *segs,
988 							int nsegs, int error)
989 {
990 	int idx;
991 	struct hpt_iop_srb *srb = (struct hpt_iop_srb *)arg;
992 	union ccb *ccb = srb->ccb;
993 	u_int8_t *cdb;
994 	struct hpt_iop_hba * hba = srb->hba;
995 	struct hpt_iop_request_scsi_command * req;
996 
997 	if (error) {
998 scsi_error:
999 		printf("hptiop: post scsi command: dma error, err = %d, nsegs = %d",
1000 					error, nsegs);
1001 		ccb->ccb_h.status = CAM_BUSY;
1002 		bus_dmamap_unload(hba->io_dmat, srb->dma_map);
1003 		hptiop_free_srb(hba, srb);
1004 		xpt_done(ccb);
1005 		return;
1006 	}
1007 
1008 	if (nsegs > hba->max_sg_count) {
1009 		printf("hptiop: nsegs is too large: nsegs=%d, Allowed count=%d",
1010 					nsegs, hba->max_sg_count);
1011 		goto scsi_error;
1012 	}
1013 
1014 	if (!srb) {
1015 		printf("hptiop: invalid srb");
1016 		goto scsi_error;
1017 	}
1018 
1019 	if (srb->srb_flag & HPT_SRB_FLAG_HIGH_MEM_ACESS) {
1020 		u_int32_t m = readl(&hba->iop->inbound_queue);
1021 
1022 		if (m == 0xFFFFFFFF) {
1023 			printf("hptiop: invaild req offset: %d", m);
1024 			goto scsi_error;
1025 		}
1026 		req = (struct hpt_iop_request_scsi_command *)((char *)hba->iop + m);
1027 	}
1028 	else
1029 		req = (struct hpt_iop_request_scsi_command *)srb;
1030 
1031 	if (ccb->csio.dxfer_len && nsegs > 0) {
1032 		struct hpt_iopsg *psg = req->sg_list;
1033 		for (idx = 0; idx < nsegs; idx++, psg++) {
1034 			psg->pci_address = (u_int64_t)segs[idx].ds_addr;
1035 			psg->size = segs[idx].ds_len;
1036 			psg->eot = 0;
1037 		}
1038 		psg[-1].eot = 1;
1039 	}
1040 
1041 	if (ccb->ccb_h.flags & CAM_CDB_POINTER)
1042 		cdb = ccb->csio.cdb_io.cdb_ptr;
1043 	else
1044 		cdb = ccb->csio.cdb_io.cdb_bytes;
1045 
1046 	bcopy(cdb, req->cdb, ccb->csio.cdb_len);
1047 
1048 	req->header.type = IOP_REQUEST_TYPE_SCSI_COMMAND;
1049 	req->header.result = IOP_RESULT_PENDING;
1050 	req->dataxfer_length = ccb->csio.dxfer_len;
1051 	req->channel =  0;
1052 	req->target =  ccb->ccb_h.target_id;
1053 	req->lun =  ccb->ccb_h.target_lun;
1054 	req->header.size = sizeof(struct hpt_iop_request_scsi_command)
1055 					- sizeof(struct hpt_iopsg) + nsegs*sizeof(struct hpt_iopsg);
1056 
1057 	if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
1058 		bus_dmamap_sync(hba->io_dmat,
1059 					srb->dma_map, BUS_DMASYNC_PREREAD);
1060 	}
1061 	else if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT)
1062 		bus_dmamap_sync(hba->io_dmat,
1063 					srb->dma_map, BUS_DMASYNC_PREWRITE);
1064 
1065 	if (srb->srb_flag & HPT_SRB_FLAG_HIGH_MEM_ACESS) {
1066 		req->header.context = (u_int64_t)(unsigned long)srb;
1067 		req->header.flags = 0;
1068 		writel(&hba->iop->inbound_queue,
1069 					((char *)req - (char *)hba->iop));
1070 	}
1071 	else {
1072 		req->header.context = (u_int64_t)srb->index |
1073 						IOPMU_QUEUE_ADDR_HOST_BIT;
1074 		req->header.flags = IOP_REQUEST_FLAG_OUTPUT_CONTEXT;
1075 
1076 		if (hba->firmware_version > 0x01020000 || hba->interface_version > 0x01020000) {
1077 			u_int32_t size_bits;
1078 
1079 			if (req->header.size < 256)
1080 				size_bits = IOPMU_QUEUE_REQUEST_SIZE_BIT;
1081 			else if (req->header.size < 512)
1082 				size_bits = IOPMU_QUEUE_ADDR_HOST_BIT;
1083 			else
1084 				size_bits = IOPMU_QUEUE_REQUEST_SIZE_BIT | IOPMU_QUEUE_ADDR_HOST_BIT;
1085 			writel(&hba->iop->inbound_queue, srb->phy_addr | size_bits);
1086 		} else
1087 			writel(&hba->iop->inbound_queue,
1088 				srb->phy_addr | IOPMU_QUEUE_ADDR_HOST_BIT);
1089 	}
1090 }
1091 
1092 static void os_request_callback(struct hpt_iop_hba * hba, u_int32_t index)
1093 {
1094 	struct hpt_iop_srb * srb;
1095 	struct hpt_iop_request_scsi_command * req;
1096 	union ccb *ccb;
1097 	u_int8_t *cdb;
1098 
1099 	if (index & IOPMU_QUEUE_MASK_HOST_BITS) {
1100 		if (hba->firmware_version > 0x01020000 || hba->interface_version > 0x01020000) {
1101 			srb = hba->srb[index & ~(u_int32_t)
1102 				(IOPMU_QUEUE_ADDR_HOST_BIT | IOPMU_QUEUE_REQUEST_RESULT_BIT)];
1103 			req = (struct hpt_iop_request_scsi_command *)srb;
1104 			if (index & IOPMU_QUEUE_REQUEST_RESULT_BIT)
1105 				req->header.result = IOP_RESULT_SUCCESS;
1106 		} else {
1107 			srb = hba->srb[index & ~(u_int32_t)IOPMU_QUEUE_ADDR_HOST_BIT];
1108 			req = (struct hpt_iop_request_scsi_command *)srb;
1109 		}
1110 		goto srb_complete;
1111 	}
1112 
1113 	req = (struct hpt_iop_request_scsi_command *)((char *)hba->iop + index);
1114 
1115 	switch(((struct hpt_iop_request_header *)req)->type) {
1116 	case IOP_REQUEST_TYPE_IOCTL_COMMAND:
1117 	{
1118 		struct hpt_iop_request_ioctl_command * p;
1119 		p = (struct hpt_iop_request_ioctl_command *)(unsigned long)
1120 				(((struct hpt_iop_request_header *)req)->context);
1121 		((struct hpt_iop_request_header *)req)->context = 0;
1122 		wakeup(req);
1123 		break;
1124 	}
1125 
1126 	case IOP_REQUEST_TYPE_SCSI_COMMAND:
1127 		srb = (struct hpt_iop_srb *)(unsigned long)req->header.context;
1128 srb_complete:
1129 		ccb = (union ccb *)srb->ccb;
1130 		if (ccb->ccb_h.flags & CAM_CDB_POINTER)
1131 			cdb = ccb->csio.cdb_io.cdb_ptr;
1132 		else
1133 			cdb = ccb->csio.cdb_io.cdb_bytes;
1134 
1135 		if (cdb[0] == SYNCHRONIZE_CACHE) { /* ??? */
1136 			ccb->ccb_h.status = CAM_REQ_CMP;
1137 			goto scsi_done;
1138 		}
1139 
1140 		switch (((struct hpt_iop_request_header *)req)->result) {
1141 		case IOP_RESULT_SUCCESS:
1142 			switch (ccb->ccb_h.flags & CAM_DIR_MASK) {
1143 			case CAM_DIR_IN:
1144 				bus_dmamap_sync(hba->io_dmat,
1145 					srb->dma_map, BUS_DMASYNC_POSTREAD);
1146 				bus_dmamap_unload(hba->io_dmat, srb->dma_map);
1147 				break;
1148 			case CAM_DIR_OUT:
1149 				bus_dmamap_sync(hba->io_dmat,
1150 					srb->dma_map, BUS_DMASYNC_POSTWRITE);
1151 				bus_dmamap_unload(hba->io_dmat, srb->dma_map);
1152 				break;
1153 			}
1154 
1155 			ccb->ccb_h.status = CAM_REQ_CMP;
1156 			break;
1157 
1158 		case IOP_RESULT_BAD_TARGET:
1159 			ccb->ccb_h.status = CAM_DEV_NOT_THERE;
1160 			break;
1161 		case IOP_RESULT_BUSY:
1162 			ccb->ccb_h.status = CAM_BUSY;
1163 			break;
1164 		case IOP_RESULT_INVALID_REQUEST:
1165 			ccb->ccb_h.status = CAM_REQ_INVALID;
1166 			break;
1167 		case IOP_RESULT_FAIL:
1168 			ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
1169 			break;
1170 		case IOP_RESULT_RESET:
1171 			ccb->ccb_h.status = CAM_BUSY;
1172 			break;
1173 		default:
1174 			ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
1175 			break;
1176 		}
1177 scsi_done:
1178 		if (srb->srb_flag & HPT_SRB_FLAG_HIGH_MEM_ACESS)
1179 			iop_post_outbound_request(hba->iop, req);
1180 
1181 		hptiop_free_srb(hba, srb);
1182 		xpt_done(ccb);
1183 		break;
1184 	}
1185 }
1186 
1187 static void hptiop_map_srb(void *arg, bus_dma_segment_t *segs,
1188 						int nsegs, int error)
1189 {
1190 	struct hpt_iop_hba * hba = (struct hpt_iop_hba *)arg;
1191 	bus_addr_t phy_addr = (segs->ds_addr + 0x1F) & ~(bus_addr_t)0x1F;
1192 	struct hpt_iop_srb *srb, *tmp_srb;
1193 	int i;
1194 
1195 	if (error || nsegs == 0) {
1196 		printf("hptiop_map_srb error");
1197 		return;
1198 	}
1199 
1200 	/* map srb */
1201 	srb = (struct hpt_iop_srb *)
1202 		(((unsigned long)hba->uncached_ptr + 0x1F) & ~(unsigned long)0x1F);
1203 
1204 	for (i = 0; i < HPT_SRB_MAX_QUEUE_SIZE; i++) {
1205 		tmp_srb = (struct hpt_iop_srb *)
1206 					((char *)srb + i * HPT_SRB_MAX_SIZE);
1207 		if (((unsigned long)tmp_srb & 0x1F) == 0) {
1208 			if (bus_dmamap_create(hba->io_dmat,
1209 						0, &tmp_srb->dma_map)) {
1210 				printf("hptiop: dmamap create failed");
1211 				return;
1212 			}
1213 
1214 			bzero(tmp_srb, sizeof(struct hpt_iop_srb));
1215 			tmp_srb->hba = hba;
1216 			tmp_srb->index = i;
1217 			if (phy_addr & IOPMU_MAX_MEM_SUPPORT_MASK_32G)
1218 				tmp_srb->srb_flag = HPT_SRB_FLAG_HIGH_MEM_ACESS;
1219 			tmp_srb->phy_addr = (u_int32_t)(phy_addr >> 5);
1220 			hptiop_free_srb(hba, tmp_srb);
1221 			hba->srb[i] = tmp_srb;
1222 			phy_addr += HPT_SRB_MAX_SIZE;
1223 		}
1224 		else {
1225 			printf("hptiop: invalid alignment");
1226 			return;
1227 		}
1228 	}
1229 }
1230 
1231 static void os_message_callback(struct hpt_iop_hba * hba, u_int32_t msg)
1232 {
1233 		hba->msg_done = 1;
1234 }
1235 
1236 static  int os_query_remove_device(struct hpt_iop_hba * hba, int target_id)
1237 {
1238 	struct cam_periph       *periph = NULL;
1239 	struct cam_path         *path;
1240 	int                     status, retval = 0;
1241 
1242 	status = xpt_create_path(&path, NULL, hba->sim->path_id, target_id, 0);
1243 
1244 	if (status == CAM_REQ_CMP) {
1245 		if ((periph = cam_periph_find(path, "da")) != NULL) {
1246 			if (periph->refcount >= 1) {
1247 				printf("hptiop: %d ,target_id=0x%x, refcount=%d",
1248 				    hba->pciunit, target_id, periph->refcount);
1249 				retval = -1;
1250 			}
1251 		}
1252 		xpt_free_path(path);
1253 	}
1254 	return retval;
1255 }
1256 
1257 static void hptiop_release_resource(struct hpt_iop_hba *hba)
1258 {
1259 	struct ccb_setasync ccb;
1260 
1261 	if (hba->path) {
1262 		xpt_setup_ccb(&ccb.ccb_h, hba->path, /*priority*/5);
1263 		ccb.ccb_h.func_code = XPT_SASYNC_CB;
1264 		ccb.event_enable = 0;
1265 		ccb.callback = hptiop_async;
1266 		ccb.callback_arg = hba->sim;
1267 		xpt_action((union ccb *)&ccb);
1268 		xpt_free_path(hba->path);
1269 	}
1270 
1271 	if (hba->sim) {
1272 		xpt_bus_deregister(cam_sim_path(hba->sim));
1273 		cam_sim_free(hba->sim, TRUE);
1274 	}
1275 
1276 	if (hba->srb_dmat) {
1277 		bus_dmamem_free(hba->srb_dmat,
1278 					hba->uncached_ptr, hba->srb_dmamap);
1279 		bus_dmamap_unload(hba->srb_dmat, hba->srb_dmamap);
1280 		bus_dma_tag_destroy(hba->srb_dmat);
1281 	}
1282 
1283 	if (hba->io_dmat)
1284 		bus_dma_tag_destroy(hba->io_dmat);
1285 
1286 	if (hba->parent_dmat)
1287 		bus_dma_tag_destroy(hba->parent_dmat);
1288 
1289 	if (hba->irq_handle)
1290 		bus_teardown_intr(hba->pcidev, hba->irq_res, hba->irq_handle);
1291 
1292 	if (hba->irq_res)
1293 		bus_release_resource(hba->pcidev, SYS_RES_IRQ, 0, hba->irq_res);
1294 
1295 	if (hba->bar0_res)
1296 		bus_release_resource(hba->pcidev, SYS_RES_MEMORY,
1297 					hba->bar0_rid, hba->bar0_res);
1298 
1299 	if (hba->ioctl_dev)
1300 		destroy_dev(hba->ioctl_dev);
1301 }
1302