1/*-
2 * Copyright 2016-2023 Microchip Technology, Inc. and/or its subsidiaries.
3 *
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/*
27 * CAM interface for smartpqi driver
28 */
29
30#include "smartpqi_includes.h"
31
32/*
33 * Set cam sim properties of the smartpqi adapter.
34 */
35static void
36update_sim_properties(struct cam_sim *sim, struct ccb_pathinq *cpi)
37{
38
39	pqisrc_softstate_t *softs = (struct pqisrc_softstate *)
40					cam_sim_softc(sim);
41
42	device_t dev = softs->os_specific.pqi_dev;
43
44	DBG_FUNC("IN\n");
45
46	cpi->version_num = 1;
47	cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE|PI_WIDE_16;
48	cpi->target_sprt = 0;
49	cpi->hba_misc = PIM_NOBUSRESET | PIM_UNMAPPED;
50	cpi->hba_eng_cnt = 0;
51	cpi->max_lun = PQI_MAX_MULTILUN;
52	cpi->max_target = MAX_TARGET_DEVICES;
53	cpi->maxio = (softs->pqi_cap.max_sg_elem - 1) * PAGE_SIZE;
54	cpi->initiator_id = 255;
55	strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN-1);
56	cpi->sim_vid[sizeof(cpi->sim_vid)-1] = '\0';
57	strncpy(cpi->hba_vid, "Microsemi", HBA_IDLEN-1);
58	cpi->hba_vid[sizeof(cpi->hba_vid)-1] = '\0';
59	strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN-1);
60	cpi->dev_name[sizeof(cpi->dev_name)-1] = '\0';
61	cpi->unit_number = cam_sim_unit(sim);
62	cpi->bus_id = cam_sim_bus(sim);
63	cpi->base_transfer_speed = 1200000; /* Base bus speed in KB/sec */
64	cpi->protocol = PROTO_SCSI;
65	cpi->protocol_version = SCSI_REV_SPC4;
66	cpi->transport = XPORT_SPI;
67	cpi->transport_version = 2;
68	cpi->ccb_h.status = CAM_REQ_CMP;
69	cpi->hba_vendor = pci_get_vendor(dev);
70	cpi->hba_device = pci_get_device(dev);
71	cpi->hba_subvendor = pci_get_subvendor(dev);
72	cpi->hba_subdevice = pci_get_subdevice(dev);
73
74
75	DBG_FUNC("OUT\n");
76}
77
78/*
79 * Get transport settings of the smartpqi adapter.
80 */
81static void
82get_transport_settings(struct pqisrc_softstate *softs,
83		struct ccb_trans_settings *cts)
84{
85	struct ccb_trans_settings_scsi	*scsi = &cts->proto_specific.scsi;
86	struct ccb_trans_settings_sas	*sas = &cts->xport_specific.sas;
87	struct ccb_trans_settings_spi	*spi = &cts->xport_specific.spi;
88
89	DBG_FUNC("IN\n");
90
91	cts->protocol = PROTO_SCSI;
92	cts->protocol_version = SCSI_REV_SPC4;
93	cts->transport = XPORT_SPI;
94	cts->transport_version = 2;
95	spi->valid = CTS_SPI_VALID_DISC;
96	spi->flags = CTS_SPI_FLAGS_DISC_ENB;
97	scsi->valid = CTS_SCSI_VALID_TQ;
98	scsi->flags = CTS_SCSI_FLAGS_TAG_ENB;
99	sas->valid = CTS_SAS_VALID_SPEED;
100	cts->ccb_h.status = CAM_REQ_CMP;
101
102	DBG_FUNC("OUT\n");
103}
104
105/*
106 *  Add the target to CAM layer and rescan, when a new device is found
107 */
108void
109os_add_device(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device)
110{
111	union ccb *ccb;
112	uint64_t lun;
113
114	DBG_FUNC("IN\n");
115
116	lun = (device->is_multi_lun) ? CAM_LUN_WILDCARD : device->lun;
117	if(softs->os_specific.sim_registered) {
118		if ((ccb = xpt_alloc_ccb_nowait()) == NULL) {
119			DBG_ERR("rescan failed (can't allocate CCB)\n");
120			return;
121		}
122
123		if (xpt_create_path(&ccb->ccb_h.path, NULL,
124			cam_sim_path(softs->os_specific.sim),
125			device->target, lun) != CAM_REQ_CMP) {
126			DBG_ERR("rescan failed (can't create path)\n");
127			xpt_free_ccb(ccb);
128			return;
129		}
130		xpt_rescan(ccb);
131	}
132
133	DBG_FUNC("OUT\n");
134}
135
136/*
137 * Remove the device from CAM layer when deleted or hot removed
138 */
139void
140os_remove_device(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device)
141{
142	struct cam_path *tmppath = NULL;
143	uint64_t lun;
144
145	DBG_FUNC("IN\n");
146
147	lun = (device->is_multi_lun) ? CAM_LUN_WILDCARD : device->lun;
148	if(softs->os_specific.sim_registered) {
149		if (xpt_create_path(&tmppath, NULL,
150			cam_sim_path(softs->os_specific.sim),
151			device->target, lun) != CAM_REQ_CMP) {
152			DBG_ERR("unable to create path for async event\n");
153			return;
154		}
155		xpt_async(AC_LOST_DEVICE, tmppath, NULL);
156		xpt_free_path(tmppath);
157		/* softs->device_list[device->target][device->lun] = NULL; */
158		int index = pqisrc_find_device_list_index(softs,device);
159		if (index >= 0 && index < PQI_MAX_DEVICES)
160			softs->dev_list[index] = NULL;
161		pqisrc_free_device(softs, device);
162	}
163
164	DBG_FUNC("OUT\n");
165
166}
167
168/*
169 * Function to release the frozen simq
170 */
171static void
172pqi_release_camq(rcb_t *rcb)
173{
174	pqisrc_softstate_t *softs;
175	struct ccb_scsiio *csio;
176
177	csio = (struct ccb_scsiio *)&rcb->cm_ccb->csio;
178	softs = rcb->softs;
179
180	DBG_FUNC("IN\n");
181
182	if (softs->os_specific.pqi_flags & PQI_FLAG_BUSY) {
183		softs->os_specific.pqi_flags &= ~PQI_FLAG_BUSY;
184		if (csio->ccb_h.status & CAM_RELEASE_SIMQ)
185			xpt_release_simq(xpt_path_sim(csio->ccb_h.path), 0);
186		else
187			csio->ccb_h.status |= CAM_RELEASE_SIMQ;
188	}
189
190	DBG_FUNC("OUT\n");
191}
192
193static void
194pqi_synch_request(rcb_t *rcb)
195{
196	pqisrc_softstate_t *softs = rcb->softs;
197
198	DBG_IO("IN rcb = %p\n", rcb);
199
200	if (!(rcb->cm_flags & PQI_CMD_MAPPED))
201		return;
202
203	if (rcb->bcount != 0 ) {
204		if ((rcb->cm_ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)
205			bus_dmamap_sync(softs->os_specific.pqi_buffer_dmat,
206					rcb->cm_datamap,BUS_DMASYNC_POSTREAD);
207		if ((rcb->cm_ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT)
208			bus_dmamap_sync(softs->os_specific.pqi_buffer_dmat,
209					rcb->cm_datamap,BUS_DMASYNC_POSTWRITE);
210		bus_dmamap_unload(softs->os_specific.pqi_buffer_dmat,
211			rcb->cm_datamap);
212	}
213	rcb->cm_flags &= ~PQI_CMD_MAPPED;
214
215	if(rcb->sgt && rcb->nseg)
216		os_mem_free(rcb->softs, (void*)rcb->sgt,
217			rcb->nseg*sizeof(sgt_t));
218
219	DBG_IO("OUT\n");
220}
221
222/*
223 * Function to dma-unmap the completed request
224 */
225static inline void
226pqi_unmap_request(rcb_t *rcb)
227{
228	DBG_IO("IN rcb = %p\n", rcb);
229
230	pqi_synch_request(rcb);
231	pqisrc_put_tag(&rcb->softs->taglist, rcb->tag);
232
233	DBG_IO("OUT\n");
234}
235
236/*
237 * Construct meaningful LD name for volume here.
238 */
239static void
240smartpqi_fix_ld_inquiry(pqisrc_softstate_t *softs, struct ccb_scsiio *csio)
241{
242	struct scsi_inquiry_data *inq = NULL;
243	uint8_t *cdb = NULL;
244	pqi_scsi_dev_t *device = NULL;
245
246	DBG_FUNC("IN\n");
247
248	if (pqisrc_ctrl_offline(softs))
249		return;
250
251 	cdb = (csio->ccb_h.flags & CAM_CDB_POINTER) ?
252		(uint8_t *)csio->cdb_io.cdb_ptr : csio->cdb_io.cdb_bytes;
253
254	if(cdb[0] == INQUIRY &&
255		(cdb[1] & SI_EVPD) == 0 &&
256		(csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN &&
257		csio->dxfer_len >= SHORT_INQUIRY_LENGTH) {
258
259		inq = (struct scsi_inquiry_data *)csio->data_ptr;
260
261		/* device = softs->device_list[csio->ccb_h.target_id][csio->ccb_h.target_lun]; */
262		int target = csio->ccb_h.target_id;
263		int lun = csio->ccb_h.target_lun;
264		int index = pqisrc_find_btl_list_index(softs,softs->bus_id,target,lun);
265		if (index != INVALID_ELEM)
266			device = softs->dev_list[index];
267
268		/* Let the disks be probed and dealt with via CAM. Only for LD
269		  let it fall through and inquiry be tweaked */
270		if( !device || 	!pqisrc_is_logical_device(device) ||
271				(device->devtype != DISK_DEVICE)  ||
272				pqisrc_is_external_raid_device(device)) {
273 	 		return;
274		}
275
276		strncpy(inq->vendor, device->vendor,
277				SID_VENDOR_SIZE-1);
278		inq->vendor[sizeof(inq->vendor)-1] = '\0';
279		strncpy(inq->product,
280				pqisrc_raidlevel_to_string(device->raid_level),
281				SID_PRODUCT_SIZE-1);
282		inq->product[sizeof(inq->product)-1] = '\0';
283		strncpy(inq->revision, device->volume_offline?"OFF":"OK",
284				SID_REVISION_SIZE-1);
285		inq->revision[sizeof(inq->revision)-1] = '\0';
286    	}
287
288	DBG_FUNC("OUT\n");
289}
290
291static void
292pqi_complete_scsi_io(struct ccb_scsiio *csio, rcb_t *rcb)
293{
294	uint32_t release_tag;
295	pqisrc_softstate_t *softs = rcb->softs;
296
297	DBG_IO("IN scsi io = %p\n", csio);
298
299	pqi_synch_request(rcb);
300	smartpqi_fix_ld_inquiry(rcb->softs, csio);
301	pqi_release_camq(rcb);
302	release_tag = rcb->tag;
303	os_reset_rcb(rcb);
304	pqisrc_put_tag(&softs->taglist, release_tag);
305	xpt_done((union ccb *)csio);
306
307	DBG_FUNC("OUT\n");
308}
309
310/*
311 * Handle completion of a command - pass results back through the CCB
312 */
313void
314os_io_response_success(rcb_t *rcb)
315{
316	struct ccb_scsiio *csio;
317
318	DBG_IO("IN rcb = %p\n", rcb);
319
320	if (rcb == NULL)
321		panic("rcb is null");
322
323	csio = (struct ccb_scsiio *)&rcb->cm_ccb->csio;
324
325	if (csio == NULL)
326		panic("csio is null");
327
328	rcb->status = PQI_STATUS_SUCCESS;
329	csio->ccb_h.status = CAM_REQ_CMP;
330
331	pqi_complete_scsi_io(csio, rcb);
332
333	DBG_IO("OUT\n");
334}
335
336static void
337copy_sense_data_to_csio(struct ccb_scsiio *csio,
338		uint8_t *sense_data, uint16_t sense_data_len)
339{
340	DBG_IO("IN csio = %p\n", csio);
341
342	memset(&csio->sense_data, 0, csio->sense_len);
343
344	sense_data_len = (sense_data_len > csio->sense_len) ?
345		csio->sense_len : sense_data_len;
346
347	if (sense_data)
348		memcpy(&csio->sense_data, sense_data, sense_data_len);
349
350	if (csio->sense_len > sense_data_len)
351		csio->sense_resid = csio->sense_len - sense_data_len;
352	else
353		csio->sense_resid = 0;
354
355	DBG_IO("OUT\n");
356}
357
358/*
359 * Error response handling for raid IO
360 */
361void
362os_raid_response_error(rcb_t *rcb, raid_path_error_info_elem_t *err_info)
363{
364	struct ccb_scsiio *csio;
365	pqisrc_softstate_t *softs;
366
367	DBG_IO("IN\n");
368
369	csio = (struct ccb_scsiio *)&rcb->cm_ccb->csio;
370
371	if (csio == NULL)
372		panic("csio is null");
373
374	softs = rcb->softs;
375
376	csio->ccb_h.status = CAM_REQ_CMP_ERR;
377
378	if (!err_info || !rcb->dvp) {
379		DBG_ERR("couldn't be accessed! error info = %p, rcb->dvp = %p\n",
380				err_info, rcb->dvp);
381		goto error_out;
382	}
383
384	csio->scsi_status = err_info->status;
385
386	if (csio->ccb_h.func_code == XPT_SCSI_IO) {
387		/*
388		 * Handle specific SCSI status values.
389		 */
390		switch(csio->scsi_status) {
391			case PQI_RAID_STATUS_QUEUE_FULL:
392				csio->ccb_h.status = CAM_REQ_CMP;
393				DBG_ERR("Queue Full error\n");
394				break;
395				/* check condition, sense data included */
396			case PQI_RAID_STATUS_CHECK_CONDITION:
397				{
398					uint16_t sense_data_len =
399						LE_16(err_info->sense_data_len);
400					uint8_t *sense_data = NULL;
401					if (sense_data_len)
402						sense_data = err_info->data;
403
404					copy_sense_data_to_csio(csio, sense_data, sense_data_len);
405					csio->ccb_h.status = CAM_SCSI_STATUS_ERROR
406						| CAM_AUTOSNS_VALID
407						| CAM_REQ_CMP_ERR;
408
409				}
410				break;
411
412			case PQI_RAID_DATA_IN_OUT_UNDERFLOW:
413				{
414					uint32_t resid = 0;
415					resid = rcb->bcount-err_info->data_out_transferred;
416					csio->resid  = resid;
417					csio->ccb_h.status = CAM_REQ_CMP;
418				}
419				break;
420			default:
421				csio->ccb_h.status = CAM_REQ_CMP;
422				break;
423		}
424	}
425
426error_out:
427	pqi_complete_scsi_io(csio, rcb);
428
429	DBG_IO("OUT\n");
430}
431
432/*
433 * Error response handling for aio.
434 */
435void
436os_aio_response_error(rcb_t *rcb, aio_path_error_info_elem_t *err_info)
437{
438	struct ccb_scsiio *csio;
439	pqisrc_softstate_t *softs;
440
441	DBG_IO("IN\n");
442
443	if (rcb == NULL)
444		panic("rcb is null");
445
446	rcb->status = PQI_STATUS_SUCCESS;
447	csio = (struct ccb_scsiio *)&rcb->cm_ccb->csio;
448	if (csio == NULL)
449                panic("csio is null");
450
451	softs = rcb->softs;
452
453	if (!err_info || !rcb->dvp) {
454		csio->ccb_h.status = CAM_REQ_CMP_ERR;
455		DBG_ERR("couldn't be accessed! error info = %p, rcb->dvp = %p\n",
456				err_info, rcb->dvp);
457		goto error_out;
458	}
459
460	switch (err_info->service_resp) {
461		case PQI_AIO_SERV_RESPONSE_COMPLETE:
462			csio->ccb_h.status = err_info->status;
463			break;
464		case PQI_AIO_SERV_RESPONSE_FAILURE:
465			switch(err_info->status) {
466				case PQI_AIO_STATUS_IO_ABORTED:
467					csio->ccb_h.status = CAM_REQ_ABORTED;
468					DBG_WARN_BTL(rcb->dvp, "IO aborted\n");
469					break;
470				case PQI_AIO_STATUS_UNDERRUN:
471					csio->ccb_h.status = CAM_REQ_CMP;
472					csio->resid =
473						LE_32(err_info->resd_count);
474					break;
475				case PQI_AIO_STATUS_OVERRUN:
476					csio->ccb_h.status = CAM_REQ_CMP;
477					break;
478				case PQI_AIO_STATUS_AIO_PATH_DISABLED:
479					DBG_WARN_BTL(rcb->dvp,"AIO Path Disabled\n");
480					/* Timed out TMF response comes here */
481					if (rcb->tm_req) {
482						rcb->req_pending = false;
483						rcb->status = PQI_STATUS_SUCCESS;
484						DBG_ERR("AIO Disabled for TMF\n");
485						return;
486					}
487					rcb->dvp->aio_enabled = false;
488					rcb->dvp->offload_enabled = false;
489					csio->ccb_h.status |= CAM_REQUEUE_REQ;
490					break;
491				case PQI_AIO_STATUS_IO_ERROR:
492				case PQI_AIO_STATUS_IO_NO_DEVICE:
493				case PQI_AIO_STATUS_INVALID_DEVICE:
494				default:
495					DBG_WARN_BTL(rcb->dvp,"IO Error/Invalid/No device\n");
496					csio->ccb_h.status |=
497						CAM_SCSI_STATUS_ERROR;
498					break;
499			}
500			break;
501		case PQI_AIO_SERV_RESPONSE_TMF_COMPLETE:
502		case PQI_AIO_SERV_RESPONSE_TMF_SUCCEEDED:
503			DBG_ERR("PQI_AIO_SERV_RESPONSE_TMF %s\n",
504				(err_info->service_resp == PQI_AIO_SERV_RESPONSE_TMF_COMPLETE) ? "COMPLETE" : "SUCCEEDED");
505			rcb->status = PQI_STATUS_SUCCESS;
506			rcb->req_pending = false;
507			return;
508		case PQI_AIO_SERV_RESPONSE_TMF_REJECTED:
509		case PQI_AIO_SERV_RESPONSE_TMF_INCORRECT_LUN:
510			DBG_ERR("PQI_AIO_SERV_RESPONSE_TMF %s\n",
511				(err_info->service_resp == PQI_AIO_SERV_RESPONSE_TMF_REJECTED) ? "REJECTED" : "INCORRECT LUN");
512			rcb->status = PQI_STATUS_TIMEOUT;
513			rcb->req_pending = false;
514			return;
515		default:
516			DBG_WARN_BTL(rcb->dvp,"Scsi Status Error\n");
517			csio->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
518			break;
519	}
520
521	if(err_info->data_pres == DATA_PRESENT_SENSE_DATA ) {
522		csio->scsi_status = PQI_AIO_STATUS_CHECK_CONDITION;
523		uint8_t *sense_data = NULL;
524		unsigned sense_data_len = LE_16(err_info->data_len);
525		if (sense_data_len)
526			sense_data = err_info->data;
527		DBG_INFO("SCSI_STATUS_CHECK_COND  sense size %u\n",
528			sense_data_len);
529		copy_sense_data_to_csio(csio, sense_data, sense_data_len);
530		csio->ccb_h.status = CAM_SCSI_STATUS_ERROR | CAM_AUTOSNS_VALID;
531	}
532
533error_out:
534	pqi_complete_scsi_io(csio, rcb);
535	DBG_IO("OUT\n");
536}
537
538static void
539pqi_freeze_ccb(union ccb *ccb)
540{
541	if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
542		ccb->ccb_h.status |= CAM_DEV_QFRZN;
543		xpt_freeze_devq(ccb->ccb_h.path, 1);
544	}
545}
546
547/*
548 * Command-mapping helper function - populate this command's s/g table.
549 */
550static void
551pqi_request_map_helper(void *arg, bus_dma_segment_t *segs, int nseg, int error)
552{
553	rcb_t *rcb = (rcb_t *)arg;
554	pqisrc_softstate_t *softs = rcb->softs;
555	union ccb *ccb;
556
557	if (error || nseg > softs->pqi_cap.max_sg_elem)
558	{
559		DBG_ERR_BTL(rcb->dvp, "map failed err = %d or nseg(%d) > sgelem(%u)\n",
560			error, nseg, softs->pqi_cap.max_sg_elem);
561		goto error_io;
562	}
563
564	rcb->sgt = os_mem_alloc(softs, nseg * sizeof(sgt_t));
565
566	if (!rcb->sgt) {
567		DBG_ERR_BTL(rcb->dvp, "os_mem_alloc() failed; nseg = %d\n", nseg);
568		goto error_io;
569	}
570
571	rcb->nseg = nseg;
572	for (int i = 0; i < nseg; i++) {
573		rcb->sgt[i].addr = segs[i].ds_addr;
574		rcb->sgt[i].len = segs[i].ds_len;
575		rcb->sgt[i].flags = 0;
576	}
577
578	if ((rcb->cm_ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)
579                bus_dmamap_sync(softs->os_specific.pqi_buffer_dmat,
580                        rcb->cm_datamap, BUS_DMASYNC_PREREAD);
581	if ((rcb->cm_ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT)
582                bus_dmamap_sync(softs->os_specific.pqi_buffer_dmat,
583                        rcb->cm_datamap, BUS_DMASYNC_PREWRITE);
584
585	/* Call IO functions depending on pd or ld */
586	rcb->status = PQI_STATUS_FAILURE;
587
588	error = pqisrc_build_send_io(softs, rcb);
589
590	if (error) {
591		rcb->req_pending = false;
592		DBG_ERR_BTL(rcb->dvp, "Build IO failed, error = %d\n", error);
593	} else {
594		/* Successfully IO was submitted to the device. */
595		return;
596	}
597
598error_io:
599	ccb = rcb->cm_ccb;
600	ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
601	pqi_freeze_ccb(ccb);
602	pqi_unmap_request(rcb);
603	xpt_done(ccb);
604	return;
605}
606
607/*
608 * Function to dma-map the request buffer
609 */
610static int
611pqi_map_request(rcb_t *rcb)
612{
613	pqisrc_softstate_t *softs = rcb->softs;
614	int bsd_status = BSD_SUCCESS;
615	union ccb *ccb = rcb->cm_ccb;
616
617	DBG_FUNC("IN\n");
618
619	/* check that mapping is necessary */
620	if (rcb->cm_flags & PQI_CMD_MAPPED)
621		return BSD_SUCCESS;
622
623	rcb->cm_flags |= PQI_CMD_MAPPED;
624
625	if (rcb->bcount) {
626		bsd_status = bus_dmamap_load_ccb(softs->os_specific.pqi_buffer_dmat,
627			rcb->cm_datamap, ccb, pqi_request_map_helper, rcb, 0);
628		if (bsd_status != BSD_SUCCESS && bsd_status != EINPROGRESS) {
629			DBG_ERR_BTL(rcb->dvp, "bus_dmamap_load_ccb failed, return status = %d transfer length = %u\n",
630					bsd_status, rcb->bcount);
631			return bsd_status;
632		}
633	} else {
634		/*
635		 * Set up the command to go to the controller.  If there are no
636		 * data buffers associated with the command then it can bypass
637		 * busdma.
638		 */
639		/* Call IO functions depending on pd or ld */
640		rcb->status = PQI_STATUS_FAILURE;
641
642		if (pqisrc_build_send_io(softs, rcb) != PQI_STATUS_SUCCESS) {
643			bsd_status = EIO;
644		}
645	}
646
647	DBG_FUNC("OUT error = %d\n", bsd_status);
648
649	return bsd_status;
650}
651
652/*
653 * Function to clear the request control block
654 */
655void
656os_reset_rcb(rcb_t *rcb)
657{
658	rcb->error_info = NULL;
659	rcb->req = NULL;
660	rcb->status = -1;
661	rcb->tag = INVALID_ELEM;
662	rcb->dvp = NULL;
663	rcb->cdbp = NULL;
664	rcb->softs = NULL;
665	rcb->cm_flags = 0;
666	rcb->cm_data = NULL;
667	rcb->bcount = 0;
668	rcb->nseg = 0;
669	rcb->sgt = NULL;
670	rcb->cm_ccb = NULL;
671	rcb->encrypt_enable = false;
672	rcb->ioaccel_handle = 0;
673	rcb->resp_qid = 0;
674	rcb->req_pending = false;
675	rcb->tm_req = false;
676}
677
678/*
679 * Callback function for the lun rescan
680 */
681static void
682smartpqi_lunrescan_cb(struct cam_periph *periph, union ccb *ccb)
683{
684        xpt_free_path(ccb->ccb_h.path);
685        xpt_free_ccb(ccb);
686}
687
688
689/*
690 * Function to rescan the lun
691 */
692static void
693smartpqi_lun_rescan(struct pqisrc_softstate *softs, int target,
694			int lun)
695{
696	union ccb *ccb = NULL;
697	cam_status status = 0;
698	struct cam_path *path = NULL;
699
700	DBG_FUNC("IN\n");
701
702	ccb = xpt_alloc_ccb_nowait();
703	if (ccb == NULL) {
704		DBG_ERR("Unable to alloc ccb for lun rescan\n");
705		return;
706	}
707
708	status = xpt_create_path(&path, NULL,
709				cam_sim_path(softs->os_specific.sim), target, lun);
710	if (status != CAM_REQ_CMP) {
711		DBG_ERR("xpt_create_path status(%d) != CAM_REQ_CMP \n",
712				 status);
713		xpt_free_ccb(ccb);
714		return;
715	}
716
717	memset(ccb, 0, sizeof(union ccb));
718	xpt_setup_ccb(&ccb->ccb_h, path, 5);
719	ccb->ccb_h.func_code = XPT_SCAN_LUN;
720	ccb->ccb_h.cbfcnp = smartpqi_lunrescan_cb;
721	ccb->crcn.flags = CAM_FLAG_NONE;
722
723	xpt_action(ccb);
724
725	DBG_FUNC("OUT\n");
726}
727
728/*
729 * Function to rescan the lun under each target
730 */
731void
732smartpqi_target_rescan(struct pqisrc_softstate *softs)
733{
734	pqi_scsi_dev_t *device;
735	int index;
736
737	DBG_FUNC("IN\n");
738
739	for(index = 0; index < PQI_MAX_DEVICES; index++){
740		/* if(softs->device_list[target][lun]){ */
741		if(softs->dev_list[index] != NULL) {
742			device = softs->dev_list[index];
743			DBG_INFO("calling smartpqi_lun_rescan with TL = %d:%d\n",device->target,device->lun);
744			smartpqi_lun_rescan(softs, device->target, device->lun);
745		}
746	}
747
748	DBG_FUNC("OUT\n");
749}
750
751/*
752 * Set the mode of tagged command queueing for the current task.
753 */
754uint8_t
755os_get_task_attr(rcb_t *rcb)
756{
757	union ccb *ccb = rcb->cm_ccb;
758	uint8_t tag_action = SOP_TASK_ATTRIBUTE_SIMPLE;
759
760	switch(ccb->csio.tag_action) {
761	case MSG_HEAD_OF_Q_TAG:
762		tag_action = SOP_TASK_ATTRIBUTE_HEAD_OF_QUEUE;
763		break;
764	case MSG_ORDERED_Q_TAG:
765		tag_action = SOP_TASK_ATTRIBUTE_ORDERED;
766		break;
767	case MSG_SIMPLE_Q_TAG:
768	default:
769		tag_action = SOP_TASK_ATTRIBUTE_SIMPLE;
770		break;
771	}
772	return tag_action;
773}
774
775/*
776 * Complete all outstanding commands
777 */
778void
779os_complete_outstanding_cmds_nodevice(pqisrc_softstate_t *softs)
780{
781	int tag = 0;
782	pqi_scsi_dev_t	*dvp = NULL;
783
784	DBG_FUNC("IN\n");
785
786	for (tag = 1; tag <= softs->max_outstanding_io; tag++) {
787		rcb_t *prcb = &softs->rcb[tag];
788		dvp = prcb->dvp;
789		if(prcb->req_pending && prcb->cm_ccb ) {
790			prcb->req_pending = false;
791			prcb->cm_ccb->ccb_h.status = CAM_REQ_ABORTED | CAM_REQ_CMP;
792			pqi_complete_scsi_io(&prcb->cm_ccb->csio, prcb);
793			if (dvp)
794				pqisrc_decrement_device_active_io(softs, dvp);
795		}
796	}
797
798	DBG_FUNC("OUT\n");
799}
800
801/*
802 * IO handling functionality entry point
803 */
804static int
805pqisrc_io_start(struct cam_sim *sim, union ccb *ccb)
806{
807	rcb_t *rcb;
808	uint32_t tag;
809	pqisrc_softstate_t *softs = (struct pqisrc_softstate *)
810					cam_sim_softc(sim);
811	int32_t error;
812	pqi_scsi_dev_t *dvp;
813	int target, lun, index;
814
815	DBG_FUNC("IN\n");
816
817	/* if( softs->device_list[ccb->ccb_h.target_id][ccb->ccb_h.target_lun] == NULL ) { */
818	target = ccb->ccb_h.target_id;
819	lun = ccb->ccb_h.target_lun;
820	index = pqisrc_find_btl_list_index(softs,softs->bus_id,target,lun);
821
822	if (index == INVALID_ELEM) {
823		ccb->ccb_h.status = CAM_DEV_NOT_THERE;
824		DBG_INFO("Invalid index/device!!!, Device BTL %u:%d:%d\n", softs->bus_id, target, lun);
825		return ENXIO;
826	}
827
828	if( softs->dev_list[index] == NULL ) {
829		ccb->ccb_h.status = CAM_DEV_NOT_THERE;
830		DBG_INFO("Device  = %d not there\n", ccb->ccb_h.target_id);
831		return ENXIO;
832	}
833
834	/* DBG_INFO("starting IO on BTL = %d:%d:%d index = %d\n",softs->bus_id,target,lun,index); */
835
836	/* dvp = softs->device_list[ccb->ccb_h.target_id][ccb->ccb_h.target_lun]; */
837	dvp = softs->dev_list[index];
838	/* Check  controller state */
839	if (IN_PQI_RESET(softs)) {
840		ccb->ccb_h.status = CAM_SCSI_BUS_RESET
841					| CAM_BUSY | CAM_REQ_INPROG;
842		DBG_WARN("Device  = %d BUSY/IN_RESET\n", ccb->ccb_h.target_id);
843		return ENXIO;
844	}
845	/* Check device state */
846	if (pqisrc_ctrl_offline(softs) || DEV_GONE(dvp)) {
847		ccb->ccb_h.status = CAM_DEV_NOT_THERE | CAM_REQ_CMP;
848		DBG_WARN("Device  = %d GONE/OFFLINE\n", ccb->ccb_h.target_id);
849		return ENXIO;
850	}
851	/* Check device reset */
852	if (DEVICE_RESET(dvp)) {
853		ccb->ccb_h.status = CAM_SCSI_BUSY | CAM_REQ_INPROG | CAM_BUSY;
854		DBG_WARN("Device %d reset returned busy\n", ccb->ccb_h.target_id);
855		return EBUSY;
856	}
857
858	if (dvp->expose_device == false) {
859		ccb->ccb_h.status = CAM_DEV_NOT_THERE;
860		DBG_INFO("Device  = %d not exposed\n", ccb->ccb_h.target_id);
861		return ENXIO;
862	}
863
864	tag = pqisrc_get_tag(&softs->taglist);
865	if( tag == INVALID_ELEM ) {
866		DBG_ERR("Get Tag failed\n");
867		xpt_freeze_simq(softs->os_specific.sim, 1);
868		softs->os_specific.pqi_flags |= PQI_FLAG_BUSY;
869		ccb->ccb_h.status |= (CAM_REQUEUE_REQ | CAM_RELEASE_SIMQ);
870		return EIO;
871	}
872
873	DBG_IO("tag = %u &softs->taglist : %p\n", tag, &softs->taglist);
874
875	rcb = &softs->rcb[tag];
876	os_reset_rcb(rcb);
877	rcb->tag = tag;
878	rcb->softs = softs;
879	rcb->cmdlen = ccb->csio.cdb_len;
880	ccb->ccb_h.sim_priv.entries[0].ptr = rcb;
881
882	rcb->cm_ccb = ccb;
883	/* rcb->dvp = softs->device_list[ccb->ccb_h.target_id][ccb->ccb_h.target_lun]; */
884	rcb->dvp = softs->dev_list[index];
885
886	rcb->cm_data = (void *)ccb->csio.data_ptr;
887	rcb->bcount = ccb->csio.dxfer_len;
888
889	/*
890	 * Submit the request to the adapter.
891	 *
892	 * Note that this may fail if we're unable to map the request (and
893	 * if we ever learn a transport layer other than simple, may fail
894	 * if the adapter rejects the command).
895	 */
896	if ((error = pqi_map_request(rcb)) != BSD_SUCCESS) {
897		xpt_freeze_simq(softs->os_specific.sim, 1);
898		if (error == EINPROGRESS) {
899			/* Release simq in the completion */
900			softs->os_specific.pqi_flags |= PQI_FLAG_BUSY;
901			error = BSD_SUCCESS;
902		} else {
903			rcb->req_pending = false;
904			ccb->ccb_h.status |= CAM_REQUEUE_REQ | CAM_RELEASE_SIMQ;
905			DBG_WARN("Requeue req error = %d target = %d\n", error,
906				ccb->ccb_h.target_id);
907			pqi_unmap_request(rcb);
908			error = EIO;
909		}
910	}
911
912	DBG_FUNC("OUT error = %d\n", error);
913
914	return error;
915}
916
917static inline int
918pqi_tmf_status_to_bsd_tmf_status(int pqi_status, rcb_t *rcb)
919{
920	if (PQI_STATUS_SUCCESS == pqi_status &&
921			PQI_STATUS_SUCCESS == rcb->status)
922		return BSD_SUCCESS;
923	else
924		return EIO;
925}
926
927/*
928 * Abort a task, task management functionality
929 */
930static int
931pqisrc_scsi_abort_task(pqisrc_softstate_t *softs,  union ccb *ccb)
932{
933	rcb_t *rcb = NULL;
934	struct ccb_hdr *ccb_h = &ccb->ccb_h;
935	rcb_t *prcb = ccb->ccb_h.sim_priv.entries[0].ptr;
936	uint32_t tag;
937	int rval;
938
939	DBG_FUNC("IN\n");
940
941	tag = pqisrc_get_tag(&softs->taglist);
942	rcb = &softs->rcb[tag];
943	rcb->tag = tag;
944
945	if (rcb->dvp == NULL) {
946		DBG_ERR("dvp is null, tmf type : 0x%x\n", ccb_h->func_code);
947		rval = ENXIO;
948		goto error_tmf;
949	}
950
951	rcb->tm_req = true;
952
953	rval = pqisrc_send_tmf(softs, rcb->dvp, rcb, prcb,
954		SOP_TASK_MANAGEMENT_FUNCTION_ABORT_TASK);
955
956	if ((rval = pqi_tmf_status_to_bsd_tmf_status(rval, rcb)) == BSD_SUCCESS)
957		ccb->ccb_h.status = CAM_REQ_ABORTED;
958
959error_tmf:
960	os_reset_rcb(rcb);
961	pqisrc_put_tag(&softs->taglist, tag);
962
963	DBG_FUNC("OUT rval = %d\n", rval);
964
965	return rval;
966}
967
968/*
969 * Abort a taskset, task management functionality
970 */
971static int
972pqisrc_scsi_abort_task_set(pqisrc_softstate_t *softs, union ccb *ccb)
973{
974	struct ccb_hdr *ccb_h = &ccb->ccb_h;
975	rcb_t *rcb = NULL;
976	uint32_t tag;
977	int rval;
978
979	DBG_FUNC("IN\n");
980
981	tag = pqisrc_get_tag(&softs->taglist);
982	rcb = &softs->rcb[tag];
983	rcb->tag = tag;
984	rcb->cm_ccb = ccb;
985
986	if (rcb->dvp == NULL) {
987		DBG_ERR("dvp is null, tmf type : 0x%x\n", ccb_h->func_code);
988		rval = ENXIO;
989		goto error_tmf;
990	}
991
992	rcb->tm_req = true;
993
994	rval = pqisrc_send_tmf(softs, rcb->dvp, rcb, NULL,
995			SOP_TASK_MANAGEMENT_FUNCTION_ABORT_TASK_SET);
996
997	rval = pqi_tmf_status_to_bsd_tmf_status(rval, rcb);
998
999error_tmf:
1000	os_reset_rcb(rcb);
1001	pqisrc_put_tag(&softs->taglist, tag);
1002
1003	DBG_FUNC("OUT rval = %d\n", rval);
1004
1005	return rval;
1006}
1007
1008/*
1009 * Target reset task management functionality
1010 */
1011static int
1012pqisrc_target_reset( pqisrc_softstate_t *softs,  union ccb *ccb)
1013{
1014
1015	/* pqi_scsi_dev_t *devp = softs->device_list[ccb->ccb_h.target_id][ccb->ccb_h.target_lun]; */
1016	struct ccb_hdr  *ccb_h = &ccb->ccb_h;
1017	rcb_t *rcb = NULL;
1018	uint32_t tag;
1019	int rval;
1020
1021	int bus, target, lun;
1022	int index;
1023
1024	DBG_FUNC("IN\n");
1025
1026	bus = softs->bus_id;
1027	target = ccb->ccb_h.target_id;
1028	lun = ccb->ccb_h.target_lun;
1029
1030	index = pqisrc_find_btl_list_index(softs,bus,target,lun);
1031	if (index == INVALID_ELEM) {
1032		DBG_ERR("device not found at BTL %d:%d:%d\n",bus,target,lun);
1033		return (-1);
1034	}
1035
1036	pqi_scsi_dev_t *devp = softs->dev_list[index];
1037	if (devp == NULL) {
1038		DBG_ERR("bad target %d, tmf type : 0x%x\n", ccb_h->target_id, ccb_h->func_code);
1039		return (-1);
1040	}
1041
1042	tag = pqisrc_get_tag(&softs->taglist);
1043	rcb = &softs->rcb[tag];
1044	rcb->tag = tag;
1045	rcb->cm_ccb = ccb;
1046
1047	rcb->tm_req = true;
1048
1049	rval = pqisrc_send_tmf(softs, devp, rcb, NULL,
1050		SOP_TASK_MANAGEMENT_LUN_RESET);
1051
1052	rval = pqi_tmf_status_to_bsd_tmf_status(rval, rcb);
1053
1054	devp->reset_in_progress = false;
1055
1056	os_reset_rcb(rcb);
1057	pqisrc_put_tag(&softs->taglist, tag);
1058
1059	DBG_FUNC("OUT rval = %d\n", rval);
1060
1061	return rval;
1062
1063}
1064
1065/*
1066 * cam entry point of the smartpqi module.
1067 */
1068static void
1069smartpqi_cam_action(struct cam_sim *sim, union ccb *ccb)
1070{
1071	struct pqisrc_softstate *softs = cam_sim_softc(sim);
1072	struct ccb_hdr  *ccb_h = &ccb->ccb_h;
1073
1074	DBG_FUNC("IN\n");
1075
1076	switch (ccb_h->func_code) {
1077		case XPT_SCSI_IO:
1078		{
1079			if(!pqisrc_io_start(sim, ccb)) {
1080				return;
1081			}
1082			break;
1083		}
1084		case XPT_CALC_GEOMETRY:
1085		{
1086			struct ccb_calc_geometry *ccg;
1087			ccg = &ccb->ccg;
1088			if (ccg->block_size == 0) {
1089				ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
1090				ccb->ccb_h.status |= CAM_REQ_INVALID;
1091				break;
1092			}
1093			cam_calc_geometry(ccg, /* extended */ 1);
1094			ccb->ccb_h.status = CAM_REQ_CMP;
1095			break;
1096		}
1097		case XPT_PATH_INQ:
1098		{
1099			update_sim_properties(sim, &ccb->cpi);
1100			ccb->ccb_h.status = CAM_REQ_CMP;
1101			break;
1102		}
1103		case XPT_GET_TRAN_SETTINGS:
1104			get_transport_settings(softs, &ccb->cts);
1105			ccb->ccb_h.status = CAM_REQ_CMP;
1106			break;
1107		case XPT_ABORT:
1108			if(pqisrc_scsi_abort_task(softs,  ccb)) {
1109				ccb->ccb_h.status = CAM_REQ_CMP_ERR;
1110				xpt_done(ccb);
1111				DBG_ERR("Abort task failed on %d\n",
1112					ccb->ccb_h.target_id);
1113				return;
1114			}
1115			break;
1116		case XPT_TERM_IO:
1117			if (pqisrc_scsi_abort_task_set(softs,  ccb)) {
1118				ccb->ccb_h.status = CAM_REQ_CMP_ERR;
1119				DBG_ERR("Abort task set failed on %d\n",
1120					ccb->ccb_h.target_id);
1121				xpt_done(ccb);
1122				return;
1123			}
1124			break;
1125		case XPT_RESET_DEV:
1126			if(pqisrc_target_reset(softs,  ccb)) {
1127				ccb->ccb_h.status = CAM_REQ_CMP_ERR;
1128				DBG_ERR("Target reset failed on %d\n",
1129					ccb->ccb_h.target_id);
1130				xpt_done(ccb);
1131				return;
1132			} else {
1133				ccb->ccb_h.status = CAM_REQ_CMP;
1134			}
1135			break;
1136		case XPT_RESET_BUS:
1137			ccb->ccb_h.status = CAM_REQ_CMP;
1138			break;
1139		case XPT_SET_TRAN_SETTINGS:
1140			ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
1141			return;
1142		default:
1143			DBG_WARN("UNSUPPORTED FUNC CODE\n");
1144			ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
1145			break;
1146	}
1147	xpt_done(ccb);
1148
1149	DBG_FUNC("OUT\n");
1150}
1151
1152/*
1153 * Function to poll the response, when interrupts are unavailable
1154 * This also serves supporting crash dump.
1155 */
1156static void
1157smartpqi_poll(struct cam_sim *sim)
1158{
1159	struct pqisrc_softstate *softs = cam_sim_softc(sim);
1160	int i;
1161
1162	for (i = 1; i < softs->intr_count; i++ )
1163		pqisrc_process_response_queue(softs, i);
1164}
1165
1166/*
1167 * Function to adjust the queue depth of a device
1168 */
1169void
1170smartpqi_adjust_queue_depth(struct cam_path *path, uint32_t queue_depth)
1171{
1172	struct ccb_relsim crs;
1173
1174	DBG_FUNC("IN\n");
1175
1176	memset(&crs, 0, sizeof(struct ccb_relsim));
1177	xpt_setup_ccb(&crs.ccb_h, path, 5);
1178	crs.ccb_h.func_code = XPT_REL_SIMQ;
1179	crs.ccb_h.flags = CAM_DEV_QFREEZE;
1180	crs.release_flags = RELSIM_ADJUST_OPENINGS;
1181	crs.openings = queue_depth;
1182	xpt_action((union ccb *)&crs);
1183	if(crs.ccb_h.status != CAM_REQ_CMP) {
1184		printf("XPT_REL_SIMQ failed stat=%d\n", crs.ccb_h.status);
1185	}
1186
1187	DBG_FUNC("OUT\n");
1188}
1189
1190/*
1191 * Function to register async callback for setting queue depth
1192 */
1193static void
1194smartpqi_async(void *callback_arg, u_int32_t code,
1195		struct cam_path *path, void *arg)
1196{
1197	struct pqisrc_softstate *softs;
1198	softs = (struct pqisrc_softstate*)callback_arg;
1199
1200	DBG_FUNC("IN\n");
1201
1202	switch (code) {
1203		case AC_FOUND_DEVICE:
1204		{
1205			struct ccb_getdev *cgd;
1206			cgd = (struct ccb_getdev *)arg;
1207			if (cgd == NULL) {
1208				break;
1209			}
1210			uint32_t t_id = cgd->ccb_h.target_id;
1211
1212			/* if (t_id <= (PQI_CTLR_INDEX - 1)) { */
1213			if (t_id >= PQI_CTLR_INDEX) {
1214				if (softs != NULL) {
1215					/* pqi_scsi_dev_t *dvp = softs->device_list[t_id][cgd->ccb_h.target_lun]; */
1216					int lun = cgd->ccb_h.target_lun;
1217					int index = pqisrc_find_btl_list_index(softs,softs->bus_id,t_id,lun);
1218					if (index != INVALID_ELEM) {
1219						pqi_scsi_dev_t *dvp = softs->dev_list[index];
1220						if (dvp == NULL) {
1221							DBG_ERR("Target is null, target id=%u\n", t_id);
1222							break;
1223						}
1224						smartpqi_adjust_queue_depth(path, dvp->queue_depth);
1225					}
1226				}
1227			}
1228			break;
1229		}
1230		default:
1231			break;
1232	}
1233
1234	DBG_FUNC("OUT\n");
1235}
1236
1237/*
1238 * Function to register sim with CAM layer for smartpqi driver
1239 */
1240int
1241register_sim(struct pqisrc_softstate *softs, int card_index)
1242{
1243	int max_transactions;
1244	union ccb   *ccb = NULL;
1245	cam_status status = 0;
1246	struct ccb_setasync csa;
1247	struct cam_sim *sim;
1248
1249	DBG_FUNC("IN\n");
1250
1251	max_transactions = softs->max_io_for_scsi_ml;
1252	softs->os_specific.devq = cam_simq_alloc(max_transactions);
1253	if (softs->os_specific.devq == NULL) {
1254		DBG_ERR("cam_simq_alloc failed txns = %d\n",
1255			max_transactions);
1256		return ENOMEM;
1257	}
1258
1259	sim = cam_sim_alloc(smartpqi_cam_action, \
1260				smartpqi_poll, "smartpqi", softs, \
1261				card_index, &softs->os_specific.cam_lock, \
1262				1, max_transactions, softs->os_specific.devq);
1263	if (sim == NULL) {
1264		DBG_ERR("cam_sim_alloc failed txns = %d\n",
1265			max_transactions);
1266		cam_simq_free(softs->os_specific.devq);
1267		return ENOMEM;
1268	}
1269
1270	softs->os_specific.sim = sim;
1271	mtx_lock(&softs->os_specific.cam_lock);
1272	status = xpt_bus_register(sim, softs->os_specific.pqi_dev, 0);
1273	if (status != CAM_SUCCESS) {
1274		DBG_ERR("xpt_bus_register failed status=%d\n", status);
1275		cam_sim_free(softs->os_specific.sim, FALSE);
1276		cam_simq_free(softs->os_specific.devq);
1277		mtx_unlock(&softs->os_specific.cam_lock);
1278		return ENXIO;
1279	}
1280
1281	softs->os_specific.sim_registered = TRUE;
1282	ccb = xpt_alloc_ccb_nowait();
1283	if (ccb == NULL) {
1284		DBG_ERR("xpt_create_path failed\n");
1285		return ENXIO;
1286	}
1287
1288	if (xpt_create_path(&ccb->ccb_h.path, NULL,
1289			cam_sim_path(softs->os_specific.sim),
1290			CAM_TARGET_WILDCARD,
1291			CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
1292		DBG_ERR("xpt_create_path failed\n");
1293		xpt_free_ccb(ccb);
1294		xpt_bus_deregister(cam_sim_path(softs->os_specific.sim));
1295		cam_sim_free(softs->os_specific.sim, TRUE);
1296		mtx_unlock(&softs->os_specific.cam_lock);
1297		return ENXIO;
1298	}
1299	/*
1300	 * Callback to set the queue depth per target which is
1301	 * derived from the FW.
1302	 */
1303	softs->os_specific.path = ccb->ccb_h.path;
1304	memset(&csa, 0, sizeof(struct ccb_setasync));
1305	xpt_setup_ccb(&csa.ccb_h, softs->os_specific.path, 5);
1306	csa.ccb_h.func_code = XPT_SASYNC_CB;
1307	csa.event_enable = AC_FOUND_DEVICE;
1308	csa.callback = smartpqi_async;
1309	csa.callback_arg = softs;
1310	xpt_action((union ccb *)&csa);
1311	if (csa.ccb_h.status != CAM_REQ_CMP) {
1312		DBG_ERR("Unable to register smartpqi_aysnc handler: %d!\n",
1313			csa.ccb_h.status);
1314	}
1315
1316	mtx_unlock(&softs->os_specific.cam_lock);
1317	DBG_FUNC("OUT\n");
1318
1319	return BSD_SUCCESS;
1320}
1321
1322/*
1323 * Function to deregister smartpqi sim from cam layer
1324 */
1325void
1326deregister_sim(struct pqisrc_softstate *softs)
1327{
1328	struct ccb_setasync csa;
1329
1330	DBG_FUNC("IN\n");
1331
1332	if (softs->os_specific.mtx_init) {
1333		mtx_lock(&softs->os_specific.cam_lock);
1334	}
1335
1336	memset(&csa, 0, sizeof(struct ccb_setasync));
1337	xpt_setup_ccb(&csa.ccb_h, softs->os_specific.path, 5);
1338	csa.ccb_h.func_code = XPT_SASYNC_CB;
1339	csa.event_enable = 0;
1340	csa.callback = smartpqi_async;
1341	csa.callback_arg = softs;
1342	xpt_action((union ccb *)&csa);
1343	xpt_free_path(softs->os_specific.path);
1344
1345	if (softs->os_specific.sim) {
1346		xpt_release_simq(softs->os_specific.sim, 0);
1347		xpt_bus_deregister(cam_sim_path(softs->os_specific.sim));
1348		softs->os_specific.sim_registered = FALSE;
1349		cam_sim_free(softs->os_specific.sim, FALSE);
1350		softs->os_specific.sim = NULL;
1351	}
1352
1353	if (softs->os_specific.mtx_init) {
1354		mtx_unlock(&softs->os_specific.cam_lock);
1355	}
1356	if (softs->os_specific.devq != NULL) {
1357		cam_simq_free(softs->os_specific.devq);
1358	}
1359	if (softs->os_specific.mtx_init) {
1360		mtx_destroy(&softs->os_specific.cam_lock);
1361		softs->os_specific.mtx_init = FALSE;
1362	}
1363
1364	mtx_destroy(&softs->os_specific.map_lock);
1365
1366	DBG_FUNC("OUT\n");
1367}
1368
1369void
1370os_rescan_target(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device)
1371{
1372	struct cam_path *tmppath = NULL;
1373
1374	DBG_FUNC("IN\n");
1375
1376	if(softs->os_specific.sim_registered) {
1377		if (xpt_create_path(&tmppath, NULL,
1378			cam_sim_path(softs->os_specific.sim),
1379			device->target, device->lun) != CAM_REQ_CMP) {
1380			DBG_ERR("unable to create path for async event!!! Bus: %d Target: %d Lun: %d\n",
1381				device->bus, device->target, device->lun);
1382			return;
1383		}
1384		xpt_async(AC_INQ_CHANGED, tmppath, NULL);
1385		xpt_free_path(tmppath);
1386	}
1387
1388	device->scsi_rescan = false;
1389
1390	DBG_FUNC("OUT\n");
1391}
1392