xref: /freebsd/sys/dev/smartpqi/smartpqi_cam.c (revision 7ea28254ec5376b5deb86c136e1838d0134dbb22)
11e66f787SSean Bruno /*-
2*7ea28254SJohn Hall  * Copyright 2016-2023 Microchip Technology, Inc. and/or its subsidiaries.
31e66f787SSean Bruno  *
41e66f787SSean Bruno  * Redistribution and use in source and binary forms, with or without
51e66f787SSean Bruno  * modification, are permitted provided that the following conditions
61e66f787SSean Bruno  * are met:
71e66f787SSean Bruno  * 1. Redistributions of source code must retain the above copyright
81e66f787SSean Bruno  *    notice, this list of conditions and the following disclaimer.
91e66f787SSean Bruno  * 2. Redistributions in binary form must reproduce the above copyright
101e66f787SSean Bruno  *    notice, this list of conditions and the following disclaimer in the
111e66f787SSean Bruno  *    documentation and/or other materials provided with the distribution.
121e66f787SSean Bruno  *
131e66f787SSean Bruno  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
141e66f787SSean Bruno  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
151e66f787SSean Bruno  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
161e66f787SSean Bruno  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
171e66f787SSean Bruno  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
181e66f787SSean Bruno  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
191e66f787SSean Bruno  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
201e66f787SSean Bruno  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
211e66f787SSean Bruno  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
221e66f787SSean Bruno  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
231e66f787SSean Bruno  * SUCH DAMAGE.
241e66f787SSean Bruno  */
251e66f787SSean Bruno 
261e66f787SSean Bruno /*
271e66f787SSean Bruno  * CAM interface for smartpqi driver
281e66f787SSean Bruno  */
291e66f787SSean Bruno 
301e66f787SSean Bruno #include "smartpqi_includes.h"
311e66f787SSean Bruno 
321e66f787SSean Bruno /*
331e66f787SSean Bruno  * Set cam sim properties of the smartpqi adapter.
341e66f787SSean Bruno  */
359fac68fcSPAPANI SRIKANTH static void
update_sim_properties(struct cam_sim * sim,struct ccb_pathinq * cpi)369fac68fcSPAPANI SRIKANTH update_sim_properties(struct cam_sim *sim, struct ccb_pathinq *cpi)
371e66f787SSean Bruno {
381e66f787SSean Bruno 
391e66f787SSean Bruno 	pqisrc_softstate_t *softs = (struct pqisrc_softstate *)
401e66f787SSean Bruno 					cam_sim_softc(sim);
419fac68fcSPAPANI SRIKANTH 
429fac68fcSPAPANI SRIKANTH 	device_t dev = softs->os_specific.pqi_dev;
439fac68fcSPAPANI SRIKANTH 
441e66f787SSean Bruno 	DBG_FUNC("IN\n");
451e66f787SSean Bruno 
461e66f787SSean Bruno 	cpi->version_num = 1;
471e66f787SSean Bruno 	cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE|PI_WIDE_16;
481e66f787SSean Bruno 	cpi->target_sprt = 0;
491e66f787SSean Bruno 	cpi->hba_misc = PIM_NOBUSRESET | PIM_UNMAPPED;
501e66f787SSean Bruno 	cpi->hba_eng_cnt = 0;
511e66f787SSean Bruno 	cpi->max_lun = PQI_MAX_MULTILUN;
52*7ea28254SJohn Hall 	cpi->max_target = MAX_TARGET_DEVICES;
531e66f787SSean Bruno 	cpi->maxio = (softs->pqi_cap.max_sg_elem - 1) * PAGE_SIZE;
541e66f787SSean Bruno 	cpi->initiator_id = 255;
55*7ea28254SJohn Hall 	strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN-1);
56*7ea28254SJohn Hall 	cpi->sim_vid[sizeof(cpi->sim_vid)-1] = '\0';
57*7ea28254SJohn Hall 	strncpy(cpi->hba_vid, "Microsemi", HBA_IDLEN-1);
58*7ea28254SJohn Hall 	cpi->hba_vid[sizeof(cpi->hba_vid)-1] = '\0';
59*7ea28254SJohn Hall 	strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN-1);
60*7ea28254SJohn Hall 	cpi->dev_name[sizeof(cpi->dev_name)-1] = '\0';
611e66f787SSean Bruno 	cpi->unit_number = cam_sim_unit(sim);
621e66f787SSean Bruno 	cpi->bus_id = cam_sim_bus(sim);
631e66f787SSean Bruno 	cpi->base_transfer_speed = 1200000; /* Base bus speed in KB/sec */
641e66f787SSean Bruno 	cpi->protocol = PROTO_SCSI;
651e66f787SSean Bruno 	cpi->protocol_version = SCSI_REV_SPC4;
661e66f787SSean Bruno 	cpi->transport = XPORT_SPI;
671e66f787SSean Bruno 	cpi->transport_version = 2;
681e66f787SSean Bruno 	cpi->ccb_h.status = CAM_REQ_CMP;
699fac68fcSPAPANI SRIKANTH 	cpi->hba_vendor = pci_get_vendor(dev);
709fac68fcSPAPANI SRIKANTH 	cpi->hba_device = pci_get_device(dev);
719fac68fcSPAPANI SRIKANTH 	cpi->hba_subvendor = pci_get_subvendor(dev);
729fac68fcSPAPANI SRIKANTH 	cpi->hba_subdevice = pci_get_subdevice(dev);
739fac68fcSPAPANI SRIKANTH 
741e66f787SSean Bruno 
751e66f787SSean Bruno 	DBG_FUNC("OUT\n");
761e66f787SSean Bruno }
771e66f787SSean Bruno 
781e66f787SSean Bruno /*
79*7ea28254SJohn Hall  * Get transport settings of the smartpqi adapter.
801e66f787SSean Bruno  */
819fac68fcSPAPANI SRIKANTH static void
get_transport_settings(struct pqisrc_softstate * softs,struct ccb_trans_settings * cts)829fac68fcSPAPANI SRIKANTH get_transport_settings(struct pqisrc_softstate *softs,
831e66f787SSean Bruno 		struct ccb_trans_settings *cts)
841e66f787SSean Bruno {
851e66f787SSean Bruno 	struct ccb_trans_settings_scsi	*scsi = &cts->proto_specific.scsi;
861e66f787SSean Bruno 	struct ccb_trans_settings_sas	*sas = &cts->xport_specific.sas;
871e66f787SSean Bruno 	struct ccb_trans_settings_spi	*spi = &cts->xport_specific.spi;
881e66f787SSean Bruno 
891e66f787SSean Bruno 	DBG_FUNC("IN\n");
901e66f787SSean Bruno 
911e66f787SSean Bruno 	cts->protocol = PROTO_SCSI;
921e66f787SSean Bruno 	cts->protocol_version = SCSI_REV_SPC4;
931e66f787SSean Bruno 	cts->transport = XPORT_SPI;
941e66f787SSean Bruno 	cts->transport_version = 2;
951e66f787SSean Bruno 	spi->valid = CTS_SPI_VALID_DISC;
961e66f787SSean Bruno 	spi->flags = CTS_SPI_FLAGS_DISC_ENB;
971e66f787SSean Bruno 	scsi->valid = CTS_SCSI_VALID_TQ;
981e66f787SSean Bruno 	scsi->flags = CTS_SCSI_FLAGS_TAG_ENB;
991e66f787SSean Bruno 	sas->valid = CTS_SAS_VALID_SPEED;
1001e66f787SSean Bruno 	cts->ccb_h.status = CAM_REQ_CMP;
1011e66f787SSean Bruno 
1021e66f787SSean Bruno 	DBG_FUNC("OUT\n");
1031e66f787SSean Bruno }
1041e66f787SSean Bruno 
1051e66f787SSean Bruno /*
1061e66f787SSean Bruno  *  Add the target to CAM layer and rescan, when a new device is found
1071e66f787SSean Bruno  */
1089fac68fcSPAPANI SRIKANTH void
os_add_device(pqisrc_softstate_t * softs,pqi_scsi_dev_t * device)1099fac68fcSPAPANI SRIKANTH os_add_device(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device)
1109fac68fcSPAPANI SRIKANTH {
1111e66f787SSean Bruno 	union ccb *ccb;
112*7ea28254SJohn Hall 	uint64_t lun;
1131e66f787SSean Bruno 
1141e66f787SSean Bruno 	DBG_FUNC("IN\n");
1151e66f787SSean Bruno 
116*7ea28254SJohn Hall 	lun = (device->is_multi_lun) ? CAM_LUN_WILDCARD : device->lun;
1171e66f787SSean Bruno 	if(softs->os_specific.sim_registered) {
1181e66f787SSean Bruno 		if ((ccb = xpt_alloc_ccb_nowait()) == NULL) {
1191e66f787SSean Bruno 			DBG_ERR("rescan failed (can't allocate CCB)\n");
1201e66f787SSean Bruno 			return;
1211e66f787SSean Bruno 		}
1221e66f787SSean Bruno 
1231e66f787SSean Bruno 		if (xpt_create_path(&ccb->ccb_h.path, NULL,
1241e66f787SSean Bruno 			cam_sim_path(softs->os_specific.sim),
125*7ea28254SJohn Hall 			device->target, lun) != CAM_REQ_CMP) {
1261e66f787SSean Bruno 			DBG_ERR("rescan failed (can't create path)\n");
1271e66f787SSean Bruno 			xpt_free_ccb(ccb);
1281e66f787SSean Bruno 			return;
1291e66f787SSean Bruno 		}
1301e66f787SSean Bruno 		xpt_rescan(ccb);
1311e66f787SSean Bruno 	}
1321e66f787SSean Bruno 
1331e66f787SSean Bruno 	DBG_FUNC("OUT\n");
1341e66f787SSean Bruno }
1351e66f787SSean Bruno 
1361e66f787SSean Bruno /*
1371e66f787SSean Bruno  * Remove the device from CAM layer when deleted or hot removed
1381e66f787SSean Bruno  */
1399fac68fcSPAPANI SRIKANTH void
os_remove_device(pqisrc_softstate_t * softs,pqi_scsi_dev_t * device)1409fac68fcSPAPANI SRIKANTH os_remove_device(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device)
1419fac68fcSPAPANI SRIKANTH {
142*7ea28254SJohn Hall 	struct cam_path *tmppath = NULL;
143*7ea28254SJohn Hall 	uint64_t lun;
1441e66f787SSean Bruno 
1451e66f787SSean Bruno 	DBG_FUNC("IN\n");
1461e66f787SSean Bruno 
147*7ea28254SJohn Hall 	lun = (device->is_multi_lun) ? CAM_LUN_WILDCARD : device->lun;
1481e66f787SSean Bruno 	if(softs->os_specific.sim_registered) {
1491e66f787SSean Bruno 		if (xpt_create_path(&tmppath, NULL,
1501e66f787SSean Bruno 			cam_sim_path(softs->os_specific.sim),
151*7ea28254SJohn Hall 			device->target, lun) != CAM_REQ_CMP) {
152*7ea28254SJohn Hall 			DBG_ERR("unable to create path for async event\n");
1531e66f787SSean Bruno 			return;
1541e66f787SSean Bruno 		}
1551e66f787SSean Bruno 		xpt_async(AC_LOST_DEVICE, tmppath, NULL);
1561e66f787SSean Bruno 		xpt_free_path(tmppath);
157*7ea28254SJohn Hall 		/* softs->device_list[device->target][device->lun] = NULL; */
158*7ea28254SJohn Hall 		int index = pqisrc_find_device_list_index(softs,device);
159*7ea28254SJohn Hall 		if (index >= 0 && index < PQI_MAX_DEVICES)
160*7ea28254SJohn Hall 			softs->dev_list[index] = NULL;
1611e66f787SSean Bruno 		pqisrc_free_device(softs, device);
1621e66f787SSean Bruno 	}
1631e66f787SSean Bruno 
1641e66f787SSean Bruno 	DBG_FUNC("OUT\n");
1651e66f787SSean Bruno 
1661e66f787SSean Bruno }
1671e66f787SSean Bruno 
1681e66f787SSean Bruno /*
1691e66f787SSean Bruno  * Function to release the frozen simq
1701e66f787SSean Bruno  */
1719fac68fcSPAPANI SRIKANTH static void
pqi_release_camq(rcb_t * rcb)1729fac68fcSPAPANI SRIKANTH pqi_release_camq(rcb_t *rcb)
1731e66f787SSean Bruno {
1741e66f787SSean Bruno 	pqisrc_softstate_t *softs;
1751e66f787SSean Bruno 	struct ccb_scsiio *csio;
1761e66f787SSean Bruno 
1771e66f787SSean Bruno 	csio = (struct ccb_scsiio *)&rcb->cm_ccb->csio;
1781e66f787SSean Bruno 	softs = rcb->softs;
1791e66f787SSean Bruno 
1801e66f787SSean Bruno 	DBG_FUNC("IN\n");
1811e66f787SSean Bruno 
1821e66f787SSean Bruno 	if (softs->os_specific.pqi_flags & PQI_FLAG_BUSY) {
1831e66f787SSean Bruno 		softs->os_specific.pqi_flags &= ~PQI_FLAG_BUSY;
1841e66f787SSean Bruno 		if (csio->ccb_h.status & CAM_RELEASE_SIMQ)
1851e66f787SSean Bruno 			xpt_release_simq(xpt_path_sim(csio->ccb_h.path), 0);
1861e66f787SSean Bruno 		else
1871e66f787SSean Bruno 			csio->ccb_h.status |= CAM_RELEASE_SIMQ;
1881e66f787SSean Bruno 	}
1891e66f787SSean Bruno 
1901e66f787SSean Bruno 	DBG_FUNC("OUT\n");
1911e66f787SSean Bruno }
1921e66f787SSean Bruno 
1939fac68fcSPAPANI SRIKANTH static void
pqi_synch_request(rcb_t * rcb)1949fac68fcSPAPANI SRIKANTH pqi_synch_request(rcb_t *rcb)
1951e66f787SSean Bruno {
1969fac68fcSPAPANI SRIKANTH 	pqisrc_softstate_t *softs = rcb->softs;
1971e66f787SSean Bruno 
1989fac68fcSPAPANI SRIKANTH 	DBG_IO("IN rcb = %p\n", rcb);
1991e66f787SSean Bruno 
2001e66f787SSean Bruno 	if (!(rcb->cm_flags & PQI_CMD_MAPPED))
2011e66f787SSean Bruno 		return;
2021e66f787SSean Bruno 
2031e66f787SSean Bruno 	if (rcb->bcount != 0 ) {
204*7ea28254SJohn Hall 		if ((rcb->cm_ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)
2051e66f787SSean Bruno 			bus_dmamap_sync(softs->os_specific.pqi_buffer_dmat,
206*7ea28254SJohn Hall 					rcb->cm_datamap,BUS_DMASYNC_POSTREAD);
207*7ea28254SJohn Hall 		if ((rcb->cm_ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT)
2081e66f787SSean Bruno 			bus_dmamap_sync(softs->os_specific.pqi_buffer_dmat,
209*7ea28254SJohn Hall 					rcb->cm_datamap,BUS_DMASYNC_POSTWRITE);
2101e66f787SSean Bruno 		bus_dmamap_unload(softs->os_specific.pqi_buffer_dmat,
2111e66f787SSean Bruno 			rcb->cm_datamap);
2121e66f787SSean Bruno 	}
2131e66f787SSean Bruno 	rcb->cm_flags &= ~PQI_CMD_MAPPED;
2141e66f787SSean Bruno 
2151e66f787SSean Bruno 	if(rcb->sgt && rcb->nseg)
2161e66f787SSean Bruno 		os_mem_free(rcb->softs, (void*)rcb->sgt,
2171e66f787SSean Bruno 			rcb->nseg*sizeof(sgt_t));
2181e66f787SSean Bruno 
2199fac68fcSPAPANI SRIKANTH 	DBG_IO("OUT\n");
2209fac68fcSPAPANI SRIKANTH }
2219fac68fcSPAPANI SRIKANTH 
2229fac68fcSPAPANI SRIKANTH /*
2239fac68fcSPAPANI SRIKANTH  * Function to dma-unmap the completed request
2249fac68fcSPAPANI SRIKANTH  */
2259fac68fcSPAPANI SRIKANTH static inline void
pqi_unmap_request(rcb_t * rcb)2269fac68fcSPAPANI SRIKANTH pqi_unmap_request(rcb_t *rcb)
2279fac68fcSPAPANI SRIKANTH {
2289fac68fcSPAPANI SRIKANTH 	DBG_IO("IN rcb = %p\n", rcb);
2299fac68fcSPAPANI SRIKANTH 
2309fac68fcSPAPANI SRIKANTH 	pqi_synch_request(rcb);
2319fac68fcSPAPANI SRIKANTH 	pqisrc_put_tag(&rcb->softs->taglist, rcb->tag);
2321e66f787SSean Bruno 
2331e66f787SSean Bruno 	DBG_IO("OUT\n");
2341e66f787SSean Bruno }
2351e66f787SSean Bruno 
2361e66f787SSean Bruno /*
2371e66f787SSean Bruno  * Construct meaningful LD name for volume here.
2381e66f787SSean Bruno  */
2391e66f787SSean Bruno static void
smartpqi_fix_ld_inquiry(pqisrc_softstate_t * softs,struct ccb_scsiio * csio)2401e66f787SSean Bruno smartpqi_fix_ld_inquiry(pqisrc_softstate_t *softs, struct ccb_scsiio *csio)
2411e66f787SSean Bruno {
2421e66f787SSean Bruno 	struct scsi_inquiry_data *inq = NULL;
2431e66f787SSean Bruno 	uint8_t *cdb = NULL;
2441e66f787SSean Bruno 	pqi_scsi_dev_t *device = NULL;
2451e66f787SSean Bruno 
2461e66f787SSean Bruno 	DBG_FUNC("IN\n");
2471e66f787SSean Bruno 
2489fac68fcSPAPANI SRIKANTH 	if (pqisrc_ctrl_offline(softs))
2499fac68fcSPAPANI SRIKANTH 		return;
2509fac68fcSPAPANI SRIKANTH 
2511e66f787SSean Bruno  	cdb = (csio->ccb_h.flags & CAM_CDB_POINTER) ?
2521e66f787SSean Bruno 		(uint8_t *)csio->cdb_io.cdb_ptr : csio->cdb_io.cdb_bytes;
253*7ea28254SJohn Hall 
2541e66f787SSean Bruno 	if(cdb[0] == INQUIRY &&
2551e66f787SSean Bruno 		(cdb[1] & SI_EVPD) == 0 &&
2561e66f787SSean Bruno 		(csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN &&
2571e66f787SSean Bruno 		csio->dxfer_len >= SHORT_INQUIRY_LENGTH) {
2589fac68fcSPAPANI SRIKANTH 
2591e66f787SSean Bruno 		inq = (struct scsi_inquiry_data *)csio->data_ptr;
2601e66f787SSean Bruno 
261*7ea28254SJohn Hall 		/* device = softs->device_list[csio->ccb_h.target_id][csio->ccb_h.target_lun]; */
262*7ea28254SJohn Hall 		int target = csio->ccb_h.target_id;
263*7ea28254SJohn Hall 		int lun = csio->ccb_h.target_lun;
264*7ea28254SJohn Hall 		int index = pqisrc_find_btl_list_index(softs,softs->bus_id,target,lun);
265*7ea28254SJohn Hall 		if (index != INVALID_ELEM)
266*7ea28254SJohn Hall 			device = softs->dev_list[index];
2671e66f787SSean Bruno 
2681e66f787SSean Bruno 		/* Let the disks be probed and dealt with via CAM. Only for LD
2691e66f787SSean Bruno 		  let it fall through and inquiry be tweaked */
2701e66f787SSean Bruno 		if( !device || 	!pqisrc_is_logical_device(device) ||
2711e66f787SSean Bruno 				(device->devtype != DISK_DEVICE)  ||
2721e66f787SSean Bruno 				pqisrc_is_external_raid_device(device)) {
2731e66f787SSean Bruno  	 		return;
2741e66f787SSean Bruno 		}
2751e66f787SSean Bruno 
2769fac68fcSPAPANI SRIKANTH 		strncpy(inq->vendor, device->vendor,
277*7ea28254SJohn Hall 				SID_VENDOR_SIZE-1);
278*7ea28254SJohn Hall 		inq->vendor[sizeof(inq->vendor)-1] = '\0';
2791e66f787SSean Bruno 		strncpy(inq->product,
2801e66f787SSean Bruno 				pqisrc_raidlevel_to_string(device->raid_level),
281*7ea28254SJohn Hall 				SID_PRODUCT_SIZE-1);
282*7ea28254SJohn Hall 		inq->product[sizeof(inq->product)-1] = '\0';
2831e66f787SSean Bruno 		strncpy(inq->revision, device->volume_offline?"OFF":"OK",
284*7ea28254SJohn Hall 				SID_REVISION_SIZE-1);
285*7ea28254SJohn Hall 		inq->revision[sizeof(inq->revision)-1] = '\0';
2861e66f787SSean Bruno     	}
2871e66f787SSean Bruno 
2881e66f787SSean Bruno 	DBG_FUNC("OUT\n");
2891e66f787SSean Bruno }
2901e66f787SSean Bruno 
2919fac68fcSPAPANI SRIKANTH static void
pqi_complete_scsi_io(struct ccb_scsiio * csio,rcb_t * rcb)2929fac68fcSPAPANI SRIKANTH pqi_complete_scsi_io(struct ccb_scsiio *csio, rcb_t *rcb)
2939fac68fcSPAPANI SRIKANTH {
2949fac68fcSPAPANI SRIKANTH 	uint32_t release_tag;
2959fac68fcSPAPANI SRIKANTH 	pqisrc_softstate_t *softs = rcb->softs;
2969fac68fcSPAPANI SRIKANTH 
2979fac68fcSPAPANI SRIKANTH 	DBG_IO("IN scsi io = %p\n", csio);
2989fac68fcSPAPANI SRIKANTH 
2999fac68fcSPAPANI SRIKANTH 	pqi_synch_request(rcb);
3009fac68fcSPAPANI SRIKANTH 	smartpqi_fix_ld_inquiry(rcb->softs, csio);
3019fac68fcSPAPANI SRIKANTH 	pqi_release_camq(rcb);
3029fac68fcSPAPANI SRIKANTH 	release_tag = rcb->tag;
3039fac68fcSPAPANI SRIKANTH 	os_reset_rcb(rcb);
3049fac68fcSPAPANI SRIKANTH 	pqisrc_put_tag(&softs->taglist, release_tag);
3059fac68fcSPAPANI SRIKANTH 	xpt_done((union ccb *)csio);
3069fac68fcSPAPANI SRIKANTH 
3079fac68fcSPAPANI SRIKANTH 	DBG_FUNC("OUT\n");
3089fac68fcSPAPANI SRIKANTH }
3099fac68fcSPAPANI SRIKANTH 
3101e66f787SSean Bruno /*
3111e66f787SSean Bruno  * Handle completion of a command - pass results back through the CCB
3121e66f787SSean Bruno  */
3131e66f787SSean Bruno void
os_io_response_success(rcb_t * rcb)3141e66f787SSean Bruno os_io_response_success(rcb_t *rcb)
3151e66f787SSean Bruno {
3161e66f787SSean Bruno 	struct ccb_scsiio *csio;
3171e66f787SSean Bruno 
3181e66f787SSean Bruno 	DBG_IO("IN rcb = %p\n", rcb);
3191e66f787SSean Bruno 
3201e66f787SSean Bruno 	if (rcb == NULL)
3211e66f787SSean Bruno 		panic("rcb is null");
3221e66f787SSean Bruno 
3231e66f787SSean Bruno 	csio = (struct ccb_scsiio *)&rcb->cm_ccb->csio;
3241e66f787SSean Bruno 
3251e66f787SSean Bruno 	if (csio == NULL)
3261e66f787SSean Bruno 		panic("csio is null");
3271e66f787SSean Bruno 
328*7ea28254SJohn Hall 	rcb->status = PQI_STATUS_SUCCESS;
3291e66f787SSean Bruno 	csio->ccb_h.status = CAM_REQ_CMP;
3301e66f787SSean Bruno 
3319fac68fcSPAPANI SRIKANTH 	pqi_complete_scsi_io(csio, rcb);
3329fac68fcSPAPANI SRIKANTH 
3339fac68fcSPAPANI SRIKANTH 	DBG_IO("OUT\n");
3349fac68fcSPAPANI SRIKANTH }
3359fac68fcSPAPANI SRIKANTH 
3369fac68fcSPAPANI SRIKANTH static void
copy_sense_data_to_csio(struct ccb_scsiio * csio,uint8_t * sense_data,uint16_t sense_data_len)3379fac68fcSPAPANI SRIKANTH copy_sense_data_to_csio(struct ccb_scsiio *csio,
3389fac68fcSPAPANI SRIKANTH 		uint8_t *sense_data, uint16_t sense_data_len)
3399fac68fcSPAPANI SRIKANTH {
3409fac68fcSPAPANI SRIKANTH 	DBG_IO("IN csio = %p\n", csio);
3419fac68fcSPAPANI SRIKANTH 
3429fac68fcSPAPANI SRIKANTH 	memset(&csio->sense_data, 0, csio->sense_len);
3439fac68fcSPAPANI SRIKANTH 
3449fac68fcSPAPANI SRIKANTH 	sense_data_len = (sense_data_len > csio->sense_len) ?
3459fac68fcSPAPANI SRIKANTH 		csio->sense_len : sense_data_len;
3469fac68fcSPAPANI SRIKANTH 
3479fac68fcSPAPANI SRIKANTH 	if (sense_data)
3489fac68fcSPAPANI SRIKANTH 		memcpy(&csio->sense_data, sense_data, sense_data_len);
3499fac68fcSPAPANI SRIKANTH 
3509fac68fcSPAPANI SRIKANTH 	if (csio->sense_len > sense_data_len)
3519fac68fcSPAPANI SRIKANTH 		csio->sense_resid = csio->sense_len - sense_data_len;
3529fac68fcSPAPANI SRIKANTH 	else
3539fac68fcSPAPANI SRIKANTH 		csio->sense_resid = 0;
3541e66f787SSean Bruno 
3551e66f787SSean Bruno 	DBG_IO("OUT\n");
3561e66f787SSean Bruno }
3571e66f787SSean Bruno 
3581e66f787SSean Bruno /*
3591e66f787SSean Bruno  * Error response handling for raid IO
3601e66f787SSean Bruno  */
3619fac68fcSPAPANI SRIKANTH void
os_raid_response_error(rcb_t * rcb,raid_path_error_info_elem_t * err_info)3629fac68fcSPAPANI SRIKANTH os_raid_response_error(rcb_t *rcb, raid_path_error_info_elem_t *err_info)
3631e66f787SSean Bruno {
3641e66f787SSean Bruno 	struct ccb_scsiio *csio;
3651e66f787SSean Bruno 	pqisrc_softstate_t *softs;
3661e66f787SSean Bruno 
3671e66f787SSean Bruno 	DBG_IO("IN\n");
3681e66f787SSean Bruno 
3691e66f787SSean Bruno 	csio = (struct ccb_scsiio *)&rcb->cm_ccb->csio;
3701e66f787SSean Bruno 
3711e66f787SSean Bruno 	if (csio == NULL)
3721e66f787SSean Bruno 		panic("csio is null");
3731e66f787SSean Bruno 
3741e66f787SSean Bruno 	softs = rcb->softs;
3751e66f787SSean Bruno 
3761e66f787SSean Bruno 	csio->ccb_h.status = CAM_REQ_CMP_ERR;
3771e66f787SSean Bruno 
3789fac68fcSPAPANI SRIKANTH 	if (!err_info || !rcb->dvp) {
3799fac68fcSPAPANI SRIKANTH 		DBG_ERR("couldn't be accessed! error info = %p, rcb->dvp = %p\n",
3809fac68fcSPAPANI SRIKANTH 				err_info, rcb->dvp);
3819fac68fcSPAPANI SRIKANTH 		goto error_out;
3829fac68fcSPAPANI SRIKANTH 	}
3839fac68fcSPAPANI SRIKANTH 
3849fac68fcSPAPANI SRIKANTH 	csio->scsi_status = err_info->status;
3859fac68fcSPAPANI SRIKANTH 
3861e66f787SSean Bruno 	if (csio->ccb_h.func_code == XPT_SCSI_IO) {
3871e66f787SSean Bruno 		/*
3881e66f787SSean Bruno 		 * Handle specific SCSI status values.
3891e66f787SSean Bruno 		 */
3901e66f787SSean Bruno 		switch(csio->scsi_status) {
3911e66f787SSean Bruno 			case PQI_RAID_STATUS_QUEUE_FULL:
3921e66f787SSean Bruno 				csio->ccb_h.status = CAM_REQ_CMP;
3939fac68fcSPAPANI SRIKANTH 				DBG_ERR("Queue Full error\n");
3941e66f787SSean Bruno 				break;
3951e66f787SSean Bruno 				/* check condition, sense data included */
3961e66f787SSean Bruno 			case PQI_RAID_STATUS_CHECK_CONDITION:
3971e66f787SSean Bruno 				{
3981e66f787SSean Bruno 					uint16_t sense_data_len =
3991e66f787SSean Bruno 						LE_16(err_info->sense_data_len);
4001e66f787SSean Bruno 					uint8_t *sense_data = NULL;
4011e66f787SSean Bruno 					if (sense_data_len)
4021e66f787SSean Bruno 						sense_data = err_info->data;
403*7ea28254SJohn Hall 
4049fac68fcSPAPANI SRIKANTH 					copy_sense_data_to_csio(csio, sense_data, sense_data_len);
4051e66f787SSean Bruno 					csio->ccb_h.status = CAM_SCSI_STATUS_ERROR
4061e66f787SSean Bruno 						| CAM_AUTOSNS_VALID
4071e66f787SSean Bruno 						| CAM_REQ_CMP_ERR;
4089fac68fcSPAPANI SRIKANTH 
4091e66f787SSean Bruno 				}
4101e66f787SSean Bruno 				break;
4111e66f787SSean Bruno 
4121e66f787SSean Bruno 			case PQI_RAID_DATA_IN_OUT_UNDERFLOW:
4131e66f787SSean Bruno 				{
4141e66f787SSean Bruno 					uint32_t resid = 0;
4151e66f787SSean Bruno 					resid = rcb->bcount-err_info->data_out_transferred;
4161e66f787SSean Bruno 					csio->resid  = resid;
4171e66f787SSean Bruno 					csio->ccb_h.status = CAM_REQ_CMP;
4181e66f787SSean Bruno 				}
4199fac68fcSPAPANI SRIKANTH 				break;
4201e66f787SSean Bruno 			default:
4211e66f787SSean Bruno 				csio->ccb_h.status = CAM_REQ_CMP;
4221e66f787SSean Bruno 				break;
4231e66f787SSean Bruno 		}
4241e66f787SSean Bruno 	}
4251e66f787SSean Bruno 
4269fac68fcSPAPANI SRIKANTH error_out:
4279fac68fcSPAPANI SRIKANTH 	pqi_complete_scsi_io(csio, rcb);
4281e66f787SSean Bruno 
4291e66f787SSean Bruno 	DBG_IO("OUT\n");
4301e66f787SSean Bruno }
4311e66f787SSean Bruno 
4321e66f787SSean Bruno /*
4331e66f787SSean Bruno  * Error response handling for aio.
4341e66f787SSean Bruno  */
4359fac68fcSPAPANI SRIKANTH void
os_aio_response_error(rcb_t * rcb,aio_path_error_info_elem_t * err_info)4369fac68fcSPAPANI SRIKANTH os_aio_response_error(rcb_t *rcb, aio_path_error_info_elem_t *err_info)
4371e66f787SSean Bruno {
4381e66f787SSean Bruno 	struct ccb_scsiio *csio;
4391e66f787SSean Bruno 	pqisrc_softstate_t *softs;
4401e66f787SSean Bruno 
4411e66f787SSean Bruno 	DBG_IO("IN\n");
4421e66f787SSean Bruno 
4431e66f787SSean Bruno 	if (rcb == NULL)
4441e66f787SSean Bruno 		panic("rcb is null");
4451e66f787SSean Bruno 
446*7ea28254SJohn Hall 	rcb->status = PQI_STATUS_SUCCESS;
4471e66f787SSean Bruno 	csio = (struct ccb_scsiio *)&rcb->cm_ccb->csio;
4481e66f787SSean Bruno 	if (csio == NULL)
4491e66f787SSean Bruno                 panic("csio is null");
4501e66f787SSean Bruno 
4511e66f787SSean Bruno 	softs = rcb->softs;
4521e66f787SSean Bruno 
4539fac68fcSPAPANI SRIKANTH 	if (!err_info || !rcb->dvp) {
4549fac68fcSPAPANI SRIKANTH 		csio->ccb_h.status = CAM_REQ_CMP_ERR;
4559fac68fcSPAPANI SRIKANTH 		DBG_ERR("couldn't be accessed! error info = %p, rcb->dvp = %p\n",
4569fac68fcSPAPANI SRIKANTH 				err_info, rcb->dvp);
4579fac68fcSPAPANI SRIKANTH 		goto error_out;
4589fac68fcSPAPANI SRIKANTH 	}
4599fac68fcSPAPANI SRIKANTH 
4601e66f787SSean Bruno 	switch (err_info->service_resp) {
4611e66f787SSean Bruno 		case PQI_AIO_SERV_RESPONSE_COMPLETE:
4621e66f787SSean Bruno 			csio->ccb_h.status = err_info->status;
4631e66f787SSean Bruno 			break;
4641e66f787SSean Bruno 		case PQI_AIO_SERV_RESPONSE_FAILURE:
4651e66f787SSean Bruno 			switch(err_info->status) {
4661e66f787SSean Bruno 				case PQI_AIO_STATUS_IO_ABORTED:
4671e66f787SSean Bruno 					csio->ccb_h.status = CAM_REQ_ABORTED;
4681e66f787SSean Bruno 					DBG_WARN_BTL(rcb->dvp, "IO aborted\n");
4691e66f787SSean Bruno 					break;
4701e66f787SSean Bruno 				case PQI_AIO_STATUS_UNDERRUN:
4711e66f787SSean Bruno 					csio->ccb_h.status = CAM_REQ_CMP;
4721e66f787SSean Bruno 					csio->resid =
4731e66f787SSean Bruno 						LE_32(err_info->resd_count);
4741e66f787SSean Bruno 					break;
4751e66f787SSean Bruno 				case PQI_AIO_STATUS_OVERRUN:
4761e66f787SSean Bruno 					csio->ccb_h.status = CAM_REQ_CMP;
4771e66f787SSean Bruno 					break;
4781e66f787SSean Bruno 				case PQI_AIO_STATUS_AIO_PATH_DISABLED:
4791e66f787SSean Bruno 					DBG_WARN_BTL(rcb->dvp,"AIO Path Disabled\n");
4809fac68fcSPAPANI SRIKANTH 					/* Timed out TMF response comes here */
4819fac68fcSPAPANI SRIKANTH 					if (rcb->tm_req) {
4829fac68fcSPAPANI SRIKANTH 						rcb->req_pending = false;
483*7ea28254SJohn Hall 						rcb->status = PQI_STATUS_SUCCESS;
4849fac68fcSPAPANI SRIKANTH 						DBG_ERR("AIO Disabled for TMF\n");
4859fac68fcSPAPANI SRIKANTH 						return;
4869fac68fcSPAPANI SRIKANTH 					}
4879fac68fcSPAPANI SRIKANTH 					rcb->dvp->aio_enabled = false;
4881e66f787SSean Bruno 					rcb->dvp->offload_enabled = false;
4891e66f787SSean Bruno 					csio->ccb_h.status |= CAM_REQUEUE_REQ;
4901e66f787SSean Bruno 					break;
4911e66f787SSean Bruno 				case PQI_AIO_STATUS_IO_ERROR:
4921e66f787SSean Bruno 				case PQI_AIO_STATUS_IO_NO_DEVICE:
4931e66f787SSean Bruno 				case PQI_AIO_STATUS_INVALID_DEVICE:
4941e66f787SSean Bruno 				default:
4951e66f787SSean Bruno 					DBG_WARN_BTL(rcb->dvp,"IO Error/Invalid/No device\n");
4961e66f787SSean Bruno 					csio->ccb_h.status |=
4971e66f787SSean Bruno 						CAM_SCSI_STATUS_ERROR;
4981e66f787SSean Bruno 					break;
4991e66f787SSean Bruno 			}
5001e66f787SSean Bruno 			break;
5011e66f787SSean Bruno 		case PQI_AIO_SERV_RESPONSE_TMF_COMPLETE:
5021e66f787SSean Bruno 		case PQI_AIO_SERV_RESPONSE_TMF_SUCCEEDED:
5039fac68fcSPAPANI SRIKANTH 			DBG_ERR("PQI_AIO_SERV_RESPONSE_TMF %s\n",
5049fac68fcSPAPANI SRIKANTH 				(err_info->service_resp == PQI_AIO_SERV_RESPONSE_TMF_COMPLETE) ? "COMPLETE" : "SUCCEEDED");
505*7ea28254SJohn Hall 			rcb->status = PQI_STATUS_SUCCESS;
5069fac68fcSPAPANI SRIKANTH 			rcb->req_pending = false;
5079fac68fcSPAPANI SRIKANTH 			return;
5081e66f787SSean Bruno 		case PQI_AIO_SERV_RESPONSE_TMF_REJECTED:
5091e66f787SSean Bruno 		case PQI_AIO_SERV_RESPONSE_TMF_INCORRECT_LUN:
5109fac68fcSPAPANI SRIKANTH 			DBG_ERR("PQI_AIO_SERV_RESPONSE_TMF %s\n",
5119fac68fcSPAPANI SRIKANTH 				(err_info->service_resp == PQI_AIO_SERV_RESPONSE_TMF_REJECTED) ? "REJECTED" : "INCORRECT LUN");
512*7ea28254SJohn Hall 			rcb->status = PQI_STATUS_TIMEOUT;
5139fac68fcSPAPANI SRIKANTH 			rcb->req_pending = false;
5149fac68fcSPAPANI SRIKANTH 			return;
5151e66f787SSean Bruno 		default:
5161e66f787SSean Bruno 			DBG_WARN_BTL(rcb->dvp,"Scsi Status Error\n");
5171e66f787SSean Bruno 			csio->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
5181e66f787SSean Bruno 			break;
5191e66f787SSean Bruno 	}
5209fac68fcSPAPANI SRIKANTH 
5211e66f787SSean Bruno 	if(err_info->data_pres == DATA_PRESENT_SENSE_DATA ) {
5221e66f787SSean Bruno 		csio->scsi_status = PQI_AIO_STATUS_CHECK_CONDITION;
5231e66f787SSean Bruno 		uint8_t *sense_data = NULL;
5241e66f787SSean Bruno 		unsigned sense_data_len = LE_16(err_info->data_len);
5251e66f787SSean Bruno 		if (sense_data_len)
5261e66f787SSean Bruno 			sense_data = err_info->data;
5274f77349dSWarner Losh 		DBG_INFO("SCSI_STATUS_CHECK_COND  sense size %u\n",
5281e66f787SSean Bruno 			sense_data_len);
5299fac68fcSPAPANI SRIKANTH 		copy_sense_data_to_csio(csio, sense_data, sense_data_len);
5301e66f787SSean Bruno 		csio->ccb_h.status = CAM_SCSI_STATUS_ERROR | CAM_AUTOSNS_VALID;
5311e66f787SSean Bruno 	}
5321e66f787SSean Bruno 
5339fac68fcSPAPANI SRIKANTH error_out:
5349fac68fcSPAPANI SRIKANTH 	pqi_complete_scsi_io(csio, rcb);
5351e66f787SSean Bruno 	DBG_IO("OUT\n");
5361e66f787SSean Bruno }
5371e66f787SSean Bruno 
5387000d321SEdward Tomasz Napierala static void
pqi_freeze_ccb(union ccb * ccb)5397000d321SEdward Tomasz Napierala pqi_freeze_ccb(union ccb *ccb)
5407000d321SEdward Tomasz Napierala {
5417000d321SEdward Tomasz Napierala 	if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
5427000d321SEdward Tomasz Napierala 		ccb->ccb_h.status |= CAM_DEV_QFRZN;
5437000d321SEdward Tomasz Napierala 		xpt_freeze_devq(ccb->ccb_h.path, 1);
5447000d321SEdward Tomasz Napierala 	}
5457000d321SEdward Tomasz Napierala }
5467000d321SEdward Tomasz Napierala 
5471e66f787SSean Bruno /*
5481e66f787SSean Bruno  * Command-mapping helper function - populate this command's s/g table.
5491e66f787SSean Bruno  */
5501e66f787SSean Bruno static void
pqi_request_map_helper(void * arg,bus_dma_segment_t * segs,int nseg,int error)5511e66f787SSean Bruno pqi_request_map_helper(void *arg, bus_dma_segment_t *segs, int nseg, int error)
5521e66f787SSean Bruno {
5539fac68fcSPAPANI SRIKANTH 	rcb_t *rcb = (rcb_t *)arg;
5549fac68fcSPAPANI SRIKANTH 	pqisrc_softstate_t *softs = rcb->softs;
5559fac68fcSPAPANI SRIKANTH 	union ccb *ccb;
5561e66f787SSean Bruno 
557*7ea28254SJohn Hall 	if (error || nseg > softs->pqi_cap.max_sg_elem)
558*7ea28254SJohn Hall 	{
559*7ea28254SJohn Hall 		DBG_ERR_BTL(rcb->dvp, "map failed err = %d or nseg(%d) > sgelem(%u)\n",
5601e66f787SSean Bruno 			error, nseg, softs->pqi_cap.max_sg_elem);
5619fac68fcSPAPANI SRIKANTH 		goto error_io;
5621e66f787SSean Bruno 	}
5631e66f787SSean Bruno 
5649fac68fcSPAPANI SRIKANTH 	rcb->sgt = os_mem_alloc(softs, nseg * sizeof(sgt_t));
5659fac68fcSPAPANI SRIKANTH 
5669fac68fcSPAPANI SRIKANTH 	if (!rcb->sgt) {
5674f4463dfSEdward Tomasz Napierala 		DBG_ERR_BTL(rcb->dvp, "os_mem_alloc() failed; nseg = %d\n", nseg);
5689fac68fcSPAPANI SRIKANTH 		goto error_io;
5694f4463dfSEdward Tomasz Napierala 	}
5704f4463dfSEdward Tomasz Napierala 
5711e66f787SSean Bruno 	rcb->nseg = nseg;
5721e66f787SSean Bruno 	for (int i = 0; i < nseg; i++) {
5731e66f787SSean Bruno 		rcb->sgt[i].addr = segs[i].ds_addr;
5741e66f787SSean Bruno 		rcb->sgt[i].len = segs[i].ds_len;
5751e66f787SSean Bruno 		rcb->sgt[i].flags = 0;
5761e66f787SSean Bruno 	}
5771e66f787SSean Bruno 
578*7ea28254SJohn Hall 	if ((rcb->cm_ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)
5791e66f787SSean Bruno                 bus_dmamap_sync(softs->os_specific.pqi_buffer_dmat,
5801e66f787SSean Bruno                         rcb->cm_datamap, BUS_DMASYNC_PREREAD);
581*7ea28254SJohn Hall 	if ((rcb->cm_ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT)
5821e66f787SSean Bruno                 bus_dmamap_sync(softs->os_specific.pqi_buffer_dmat,
5831e66f787SSean Bruno                         rcb->cm_datamap, BUS_DMASYNC_PREWRITE);
5841e66f787SSean Bruno 
5851e66f787SSean Bruno 	/* Call IO functions depending on pd or ld */
586*7ea28254SJohn Hall 	rcb->status = PQI_STATUS_FAILURE;
5871e66f787SSean Bruno 
5881e66f787SSean Bruno 	error = pqisrc_build_send_io(softs, rcb);
5891e66f787SSean Bruno 
5901e66f787SSean Bruno 	if (error) {
5911e66f787SSean Bruno 		rcb->req_pending = false;
5921e66f787SSean Bruno 		DBG_ERR_BTL(rcb->dvp, "Build IO failed, error = %d\n", error);
5939fac68fcSPAPANI SRIKANTH 	} else {
5949fac68fcSPAPANI SRIKANTH 		/* Successfully IO was submitted to the device. */
5951e66f787SSean Bruno 		return;
5961e66f787SSean Bruno 	}
5979fac68fcSPAPANI SRIKANTH 
5989fac68fcSPAPANI SRIKANTH error_io:
5999fac68fcSPAPANI SRIKANTH 	ccb = rcb->cm_ccb;
6009fac68fcSPAPANI SRIKANTH 	ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
6019fac68fcSPAPANI SRIKANTH 	pqi_freeze_ccb(ccb);
6029fac68fcSPAPANI SRIKANTH 	pqi_unmap_request(rcb);
6039fac68fcSPAPANI SRIKANTH 	xpt_done(ccb);
6049fac68fcSPAPANI SRIKANTH 	return;
6051e66f787SSean Bruno }
6061e66f787SSean Bruno 
6071e66f787SSean Bruno /*
6081e66f787SSean Bruno  * Function to dma-map the request buffer
6091e66f787SSean Bruno  */
6109fac68fcSPAPANI SRIKANTH static int
pqi_map_request(rcb_t * rcb)6119fac68fcSPAPANI SRIKANTH pqi_map_request(rcb_t *rcb)
6121e66f787SSean Bruno {
6131e66f787SSean Bruno 	pqisrc_softstate_t *softs = rcb->softs;
6149fac68fcSPAPANI SRIKANTH 	int bsd_status = BSD_SUCCESS;
6151e66f787SSean Bruno 	union ccb *ccb = rcb->cm_ccb;
6161e66f787SSean Bruno 
6171e66f787SSean Bruno 	DBG_FUNC("IN\n");
6181e66f787SSean Bruno 
6191e66f787SSean Bruno 	/* check that mapping is necessary */
6201e66f787SSean Bruno 	if (rcb->cm_flags & PQI_CMD_MAPPED)
6219fac68fcSPAPANI SRIKANTH 		return BSD_SUCCESS;
6229fac68fcSPAPANI SRIKANTH 
6231e66f787SSean Bruno 	rcb->cm_flags |= PQI_CMD_MAPPED;
6241e66f787SSean Bruno 
6251e66f787SSean Bruno 	if (rcb->bcount) {
6269fac68fcSPAPANI SRIKANTH 		bsd_status = bus_dmamap_load_ccb(softs->os_specific.pqi_buffer_dmat,
6271e66f787SSean Bruno 			rcb->cm_datamap, ccb, pqi_request_map_helper, rcb, 0);
6289fac68fcSPAPANI SRIKANTH 		if (bsd_status != BSD_SUCCESS && bsd_status != EINPROGRESS) {
629*7ea28254SJohn Hall 			DBG_ERR_BTL(rcb->dvp, "bus_dmamap_load_ccb failed, return status = %d transfer length = %u\n",
6309fac68fcSPAPANI SRIKANTH 					bsd_status, rcb->bcount);
6319fac68fcSPAPANI SRIKANTH 			return bsd_status;
6321e66f787SSean Bruno 		}
6331e66f787SSean Bruno 	} else {
6341e66f787SSean Bruno 		/*
6351e66f787SSean Bruno 		 * Set up the command to go to the controller.  If there are no
6361e66f787SSean Bruno 		 * data buffers associated with the command then it can bypass
6371e66f787SSean Bruno 		 * busdma.
6381e66f787SSean Bruno 		 */
6391e66f787SSean Bruno 		/* Call IO functions depending on pd or ld */
640*7ea28254SJohn Hall 		rcb->status = PQI_STATUS_FAILURE;
6411e66f787SSean Bruno 
6429fac68fcSPAPANI SRIKANTH 		if (pqisrc_build_send_io(softs, rcb) != PQI_STATUS_SUCCESS) {
6439fac68fcSPAPANI SRIKANTH 			bsd_status = EIO;
6449fac68fcSPAPANI SRIKANTH 		}
6451e66f787SSean Bruno 	}
6461e66f787SSean Bruno 
6479fac68fcSPAPANI SRIKANTH 	DBG_FUNC("OUT error = %d\n", bsd_status);
6481e66f787SSean Bruno 
6499fac68fcSPAPANI SRIKANTH 	return bsd_status;
6501e66f787SSean Bruno }
6511e66f787SSean Bruno 
6521e66f787SSean Bruno /*
6531e66f787SSean Bruno  * Function to clear the request control block
6541e66f787SSean Bruno  */
6559fac68fcSPAPANI SRIKANTH void
os_reset_rcb(rcb_t * rcb)6569fac68fcSPAPANI SRIKANTH os_reset_rcb(rcb_t *rcb)
6571e66f787SSean Bruno {
6581e66f787SSean Bruno 	rcb->error_info = NULL;
6591e66f787SSean Bruno 	rcb->req = NULL;
6601e66f787SSean Bruno 	rcb->status = -1;
6611e66f787SSean Bruno 	rcb->tag = INVALID_ELEM;
6621e66f787SSean Bruno 	rcb->dvp = NULL;
6631e66f787SSean Bruno 	rcb->cdbp = NULL;
6641e66f787SSean Bruno 	rcb->softs = NULL;
6651e66f787SSean Bruno 	rcb->cm_flags = 0;
6661e66f787SSean Bruno 	rcb->cm_data = NULL;
6671e66f787SSean Bruno 	rcb->bcount = 0;
6681e66f787SSean Bruno 	rcb->nseg = 0;
6691e66f787SSean Bruno 	rcb->sgt = NULL;
6701e66f787SSean Bruno 	rcb->cm_ccb = NULL;
6711e66f787SSean Bruno 	rcb->encrypt_enable = false;
6721e66f787SSean Bruno 	rcb->ioaccel_handle = 0;
6731e66f787SSean Bruno 	rcb->resp_qid = 0;
6741e66f787SSean Bruno 	rcb->req_pending = false;
6759fac68fcSPAPANI SRIKANTH 	rcb->tm_req = false;
6761e66f787SSean Bruno }
6771e66f787SSean Bruno 
6781e66f787SSean Bruno /*
6791e66f787SSean Bruno  * Callback function for the lun rescan
6801e66f787SSean Bruno  */
6819fac68fcSPAPANI SRIKANTH static void
smartpqi_lunrescan_cb(struct cam_periph * periph,union ccb * ccb)6829fac68fcSPAPANI SRIKANTH smartpqi_lunrescan_cb(struct cam_periph *periph, union ccb *ccb)
6831e66f787SSean Bruno {
6841e66f787SSean Bruno         xpt_free_path(ccb->ccb_h.path);
6851e66f787SSean Bruno         xpt_free_ccb(ccb);
6861e66f787SSean Bruno }
6871e66f787SSean Bruno 
6889fac68fcSPAPANI SRIKANTH 
6891e66f787SSean Bruno /*
6901e66f787SSean Bruno  * Function to rescan the lun
6911e66f787SSean Bruno  */
6929fac68fcSPAPANI SRIKANTH static void
smartpqi_lun_rescan(struct pqisrc_softstate * softs,int target,int lun)6939fac68fcSPAPANI SRIKANTH smartpqi_lun_rescan(struct pqisrc_softstate *softs, int target,
6941e66f787SSean Bruno 			int lun)
6951e66f787SSean Bruno {
6961e66f787SSean Bruno 	union ccb *ccb = NULL;
6971e66f787SSean Bruno 	cam_status status = 0;
6981e66f787SSean Bruno 	struct cam_path *path = NULL;
6991e66f787SSean Bruno 
7001e66f787SSean Bruno 	DBG_FUNC("IN\n");
7011e66f787SSean Bruno 
7021e66f787SSean Bruno 	ccb = xpt_alloc_ccb_nowait();
7039fac68fcSPAPANI SRIKANTH 	if (ccb == NULL) {
7049fac68fcSPAPANI SRIKANTH 		DBG_ERR("Unable to alloc ccb for lun rescan\n");
7059fac68fcSPAPANI SRIKANTH 		return;
7069fac68fcSPAPANI SRIKANTH 	}
7079fac68fcSPAPANI SRIKANTH 
7081e66f787SSean Bruno 	status = xpt_create_path(&path, NULL,
7091e66f787SSean Bruno 				cam_sim_path(softs->os_specific.sim), target, lun);
7101e66f787SSean Bruno 	if (status != CAM_REQ_CMP) {
7111e66f787SSean Bruno 		DBG_ERR("xpt_create_path status(%d) != CAM_REQ_CMP \n",
7121e66f787SSean Bruno 				 status);
7131e66f787SSean Bruno 		xpt_free_ccb(ccb);
7141e66f787SSean Bruno 		return;
7151e66f787SSean Bruno 	}
7161e66f787SSean Bruno 
717*7ea28254SJohn Hall 	memset(ccb, 0, sizeof(union ccb));
7181e66f787SSean Bruno 	xpt_setup_ccb(&ccb->ccb_h, path, 5);
7191e66f787SSean Bruno 	ccb->ccb_h.func_code = XPT_SCAN_LUN;
7201e66f787SSean Bruno 	ccb->ccb_h.cbfcnp = smartpqi_lunrescan_cb;
7211e66f787SSean Bruno 	ccb->crcn.flags = CAM_FLAG_NONE;
7221e66f787SSean Bruno 
7231e66f787SSean Bruno 	xpt_action(ccb);
7241e66f787SSean Bruno 
7251e66f787SSean Bruno 	DBG_FUNC("OUT\n");
7261e66f787SSean Bruno }
7271e66f787SSean Bruno 
7281e66f787SSean Bruno /*
7291e66f787SSean Bruno  * Function to rescan the lun under each target
7301e66f787SSean Bruno  */
7319fac68fcSPAPANI SRIKANTH void
smartpqi_target_rescan(struct pqisrc_softstate * softs)7329fac68fcSPAPANI SRIKANTH smartpqi_target_rescan(struct pqisrc_softstate *softs)
7331e66f787SSean Bruno {
734*7ea28254SJohn Hall 	pqi_scsi_dev_t *device;
735*7ea28254SJohn Hall 	int index;
7361e66f787SSean Bruno 
7371e66f787SSean Bruno 	DBG_FUNC("IN\n");
7381e66f787SSean Bruno 
739*7ea28254SJohn Hall 	for(index = 0; index < PQI_MAX_DEVICES; index++){
740*7ea28254SJohn Hall 		/* if(softs->device_list[target][lun]){ */
741*7ea28254SJohn Hall 		if(softs->dev_list[index] != NULL) {
742*7ea28254SJohn Hall 			device = softs->dev_list[index];
743*7ea28254SJohn Hall 			DBG_INFO("calling smartpqi_lun_rescan with TL = %d:%d\n",device->target,device->lun);
744*7ea28254SJohn Hall 			smartpqi_lun_rescan(softs, device->target, device->lun);
7451e66f787SSean Bruno 		}
7461e66f787SSean Bruno 	}
7471e66f787SSean Bruno 
7481e66f787SSean Bruno 	DBG_FUNC("OUT\n");
7491e66f787SSean Bruno }
7501e66f787SSean Bruno 
7511e66f787SSean Bruno /*
7521e66f787SSean Bruno  * Set the mode of tagged command queueing for the current task.
7531e66f787SSean Bruno  */
7549fac68fcSPAPANI SRIKANTH uint8_t
os_get_task_attr(rcb_t * rcb)7559fac68fcSPAPANI SRIKANTH os_get_task_attr(rcb_t *rcb)
7561e66f787SSean Bruno {
7571e66f787SSean Bruno 	union ccb *ccb = rcb->cm_ccb;
7581e66f787SSean Bruno 	uint8_t tag_action = SOP_TASK_ATTRIBUTE_SIMPLE;
7591e66f787SSean Bruno 
7601e66f787SSean Bruno 	switch(ccb->csio.tag_action) {
7611e66f787SSean Bruno 	case MSG_HEAD_OF_Q_TAG:
7621e66f787SSean Bruno 		tag_action = SOP_TASK_ATTRIBUTE_HEAD_OF_QUEUE;
7631e66f787SSean Bruno 		break;
7641e66f787SSean Bruno 	case MSG_ORDERED_Q_TAG:
7651e66f787SSean Bruno 		tag_action = SOP_TASK_ATTRIBUTE_ORDERED;
7661e66f787SSean Bruno 		break;
7671e66f787SSean Bruno 	case MSG_SIMPLE_Q_TAG:
7681e66f787SSean Bruno 	default:
7691e66f787SSean Bruno 		tag_action = SOP_TASK_ATTRIBUTE_SIMPLE;
7701e66f787SSean Bruno 		break;
7711e66f787SSean Bruno 	}
7721e66f787SSean Bruno 	return tag_action;
7731e66f787SSean Bruno }
7741e66f787SSean Bruno 
7751e66f787SSean Bruno /*
7761e66f787SSean Bruno  * Complete all outstanding commands
7771e66f787SSean Bruno  */
7789fac68fcSPAPANI SRIKANTH void
os_complete_outstanding_cmds_nodevice(pqisrc_softstate_t * softs)7799fac68fcSPAPANI SRIKANTH os_complete_outstanding_cmds_nodevice(pqisrc_softstate_t *softs)
7801e66f787SSean Bruno {
7811e66f787SSean Bruno 	int tag = 0;
7829fac68fcSPAPANI SRIKANTH 	pqi_scsi_dev_t	*dvp = NULL;
7831e66f787SSean Bruno 
7841e66f787SSean Bruno 	DBG_FUNC("IN\n");
7851e66f787SSean Bruno 
7869fac68fcSPAPANI SRIKANTH 	for (tag = 1; tag <= softs->max_outstanding_io; tag++) {
7871e66f787SSean Bruno 		rcb_t *prcb = &softs->rcb[tag];
7889fac68fcSPAPANI SRIKANTH 		dvp = prcb->dvp;
7891e66f787SSean Bruno 		if(prcb->req_pending && prcb->cm_ccb ) {
7901e66f787SSean Bruno 			prcb->req_pending = false;
7911e66f787SSean Bruno 			prcb->cm_ccb->ccb_h.status = CAM_REQ_ABORTED | CAM_REQ_CMP;
7929fac68fcSPAPANI SRIKANTH 			pqi_complete_scsi_io(&prcb->cm_ccb->csio, prcb);
7939fac68fcSPAPANI SRIKANTH 			if (dvp)
7949fac68fcSPAPANI SRIKANTH 				pqisrc_decrement_device_active_io(softs, dvp);
7951e66f787SSean Bruno 		}
7961e66f787SSean Bruno 	}
7971e66f787SSean Bruno 
7981e66f787SSean Bruno 	DBG_FUNC("OUT\n");
7991e66f787SSean Bruno }
8001e66f787SSean Bruno 
8011e66f787SSean Bruno /*
8021e66f787SSean Bruno  * IO handling functionality entry point
8031e66f787SSean Bruno  */
8049fac68fcSPAPANI SRIKANTH static int
pqisrc_io_start(struct cam_sim * sim,union ccb * ccb)8059fac68fcSPAPANI SRIKANTH pqisrc_io_start(struct cam_sim *sim, union ccb *ccb)
8061e66f787SSean Bruno {
8071e66f787SSean Bruno 	rcb_t *rcb;
808*7ea28254SJohn Hall 	uint32_t tag;
8091e66f787SSean Bruno 	pqisrc_softstate_t *softs = (struct pqisrc_softstate *)
8101e66f787SSean Bruno 					cam_sim_softc(sim);
8119fac68fcSPAPANI SRIKANTH 	int32_t error;
8121e66f787SSean Bruno 	pqi_scsi_dev_t *dvp;
813*7ea28254SJohn Hall 	int target, lun, index;
8141e66f787SSean Bruno 
8151e66f787SSean Bruno 	DBG_FUNC("IN\n");
8161e66f787SSean Bruno 
817*7ea28254SJohn Hall 	/* if( softs->device_list[ccb->ccb_h.target_id][ccb->ccb_h.target_lun] == NULL ) { */
818*7ea28254SJohn Hall 	target = ccb->ccb_h.target_id;
819*7ea28254SJohn Hall 	lun = ccb->ccb_h.target_lun;
820*7ea28254SJohn Hall 	index = pqisrc_find_btl_list_index(softs,softs->bus_id,target,lun);
821*7ea28254SJohn Hall 
822*7ea28254SJohn Hall 	if (index == INVALID_ELEM) {
823*7ea28254SJohn Hall 		ccb->ccb_h.status = CAM_DEV_NOT_THERE;
824*7ea28254SJohn Hall 		DBG_INFO("Invalid index/device!!!, Device BTL %u:%d:%d\n", softs->bus_id, target, lun);
825*7ea28254SJohn Hall 		return ENXIO;
826*7ea28254SJohn Hall 	}
827*7ea28254SJohn Hall 
828*7ea28254SJohn Hall 	if( softs->dev_list[index] == NULL ) {
8291e66f787SSean Bruno 		ccb->ccb_h.status = CAM_DEV_NOT_THERE;
8301e66f787SSean Bruno 		DBG_INFO("Device  = %d not there\n", ccb->ccb_h.target_id);
8319fac68fcSPAPANI SRIKANTH 		return ENXIO;
8321e66f787SSean Bruno 	}
8331e66f787SSean Bruno 
834*7ea28254SJohn Hall 	/* DBG_INFO("starting IO on BTL = %d:%d:%d index = %d\n",softs->bus_id,target,lun,index); */
835*7ea28254SJohn Hall 
836*7ea28254SJohn Hall 	/* dvp = softs->device_list[ccb->ccb_h.target_id][ccb->ccb_h.target_lun]; */
837*7ea28254SJohn Hall 	dvp = softs->dev_list[index];
8381e66f787SSean Bruno 	/* Check  controller state */
8391e66f787SSean Bruno 	if (IN_PQI_RESET(softs)) {
8401e66f787SSean Bruno 		ccb->ccb_h.status = CAM_SCSI_BUS_RESET
8411e66f787SSean Bruno 					| CAM_BUSY | CAM_REQ_INPROG;
8421e66f787SSean Bruno 		DBG_WARN("Device  = %d BUSY/IN_RESET\n", ccb->ccb_h.target_id);
8439fac68fcSPAPANI SRIKANTH 		return ENXIO;
8441e66f787SSean Bruno 	}
8451e66f787SSean Bruno 	/* Check device state */
8461e66f787SSean Bruno 	if (pqisrc_ctrl_offline(softs) || DEV_GONE(dvp)) {
8471e66f787SSean Bruno 		ccb->ccb_h.status = CAM_DEV_NOT_THERE | CAM_REQ_CMP;
8481e66f787SSean Bruno 		DBG_WARN("Device  = %d GONE/OFFLINE\n", ccb->ccb_h.target_id);
8499fac68fcSPAPANI SRIKANTH 		return ENXIO;
8501e66f787SSean Bruno 	}
8511e66f787SSean Bruno 	/* Check device reset */
8529fac68fcSPAPANI SRIKANTH 	if (DEVICE_RESET(dvp)) {
8531e66f787SSean Bruno 		ccb->ccb_h.status = CAM_SCSI_BUSY | CAM_REQ_INPROG | CAM_BUSY;
8541e66f787SSean Bruno 		DBG_WARN("Device %d reset returned busy\n", ccb->ccb_h.target_id);
8559fac68fcSPAPANI SRIKANTH 		return EBUSY;
8561e66f787SSean Bruno 	}
8571e66f787SSean Bruno 
8581e66f787SSean Bruno 	if (dvp->expose_device == false) {
8591e66f787SSean Bruno 		ccb->ccb_h.status = CAM_DEV_NOT_THERE;
8601e66f787SSean Bruno 		DBG_INFO("Device  = %d not exposed\n", ccb->ccb_h.target_id);
8619fac68fcSPAPANI SRIKANTH 		return ENXIO;
8621e66f787SSean Bruno 	}
8631e66f787SSean Bruno 
8641e66f787SSean Bruno 	tag = pqisrc_get_tag(&softs->taglist);
8651e66f787SSean Bruno 	if( tag == INVALID_ELEM ) {
8661e66f787SSean Bruno 		DBG_ERR("Get Tag failed\n");
8671e66f787SSean Bruno 		xpt_freeze_simq(softs->os_specific.sim, 1);
8681e66f787SSean Bruno 		softs->os_specific.pqi_flags |= PQI_FLAG_BUSY;
8691e66f787SSean Bruno 		ccb->ccb_h.status |= (CAM_REQUEUE_REQ | CAM_RELEASE_SIMQ);
8709fac68fcSPAPANI SRIKANTH 		return EIO;
8711e66f787SSean Bruno 	}
8721e66f787SSean Bruno 
873*7ea28254SJohn Hall 	DBG_IO("tag = %u &softs->taglist : %p\n", tag, &softs->taglist);
8741e66f787SSean Bruno 
8751e66f787SSean Bruno 	rcb = &softs->rcb[tag];
8761e66f787SSean Bruno 	os_reset_rcb(rcb);
8771e66f787SSean Bruno 	rcb->tag = tag;
8781e66f787SSean Bruno 	rcb->softs = softs;
8791e66f787SSean Bruno 	rcb->cmdlen = ccb->csio.cdb_len;
8801e66f787SSean Bruno 	ccb->ccb_h.sim_priv.entries[0].ptr = rcb;
8811e66f787SSean Bruno 
8821e66f787SSean Bruno 	rcb->cm_ccb = ccb;
883*7ea28254SJohn Hall 	/* rcb->dvp = softs->device_list[ccb->ccb_h.target_id][ccb->ccb_h.target_lun]; */
884*7ea28254SJohn Hall 	rcb->dvp = softs->dev_list[index];
8851e66f787SSean Bruno 
8861e66f787SSean Bruno 	rcb->cm_data = (void *)ccb->csio.data_ptr;
8871e66f787SSean Bruno 	rcb->bcount = ccb->csio.dxfer_len;
888*7ea28254SJohn Hall 
8891e66f787SSean Bruno 	/*
8901e66f787SSean Bruno 	 * Submit the request to the adapter.
8911e66f787SSean Bruno 	 *
8921e66f787SSean Bruno 	 * Note that this may fail if we're unable to map the request (and
8931e66f787SSean Bruno 	 * if we ever learn a transport layer other than simple, may fail
8941e66f787SSean Bruno 	 * if the adapter rejects the command).
8951e66f787SSean Bruno 	 */
8969fac68fcSPAPANI SRIKANTH 	if ((error = pqi_map_request(rcb)) != BSD_SUCCESS) {
8971e66f787SSean Bruno 		xpt_freeze_simq(softs->os_specific.sim, 1);
8981e66f787SSean Bruno 		if (error == EINPROGRESS) {
8999fac68fcSPAPANI SRIKANTH 			/* Release simq in the completion */
9009fac68fcSPAPANI SRIKANTH 			softs->os_specific.pqi_flags |= PQI_FLAG_BUSY;
9019fac68fcSPAPANI SRIKANTH 			error = BSD_SUCCESS;
9021e66f787SSean Bruno 		} else {
9039fac68fcSPAPANI SRIKANTH 			rcb->req_pending = false;
9049fac68fcSPAPANI SRIKANTH 			ccb->ccb_h.status |= CAM_REQUEUE_REQ | CAM_RELEASE_SIMQ;
9051e66f787SSean Bruno 			DBG_WARN("Requeue req error = %d target = %d\n", error,
9061e66f787SSean Bruno 				ccb->ccb_h.target_id);
9071e66f787SSean Bruno 			pqi_unmap_request(rcb);
9089fac68fcSPAPANI SRIKANTH 			error = EIO;
9091e66f787SSean Bruno 		}
9101e66f787SSean Bruno 	}
9111e66f787SSean Bruno 
9121e66f787SSean Bruno 	DBG_FUNC("OUT error = %d\n", error);
9139fac68fcSPAPANI SRIKANTH 
9141e66f787SSean Bruno 	return error;
9151e66f787SSean Bruno }
9161e66f787SSean Bruno 
9179fac68fcSPAPANI SRIKANTH static inline int
pqi_tmf_status_to_bsd_tmf_status(int pqi_status,rcb_t * rcb)9189fac68fcSPAPANI SRIKANTH pqi_tmf_status_to_bsd_tmf_status(int pqi_status, rcb_t *rcb)
9199fac68fcSPAPANI SRIKANTH {
9209fac68fcSPAPANI SRIKANTH 	if (PQI_STATUS_SUCCESS == pqi_status &&
921*7ea28254SJohn Hall 			PQI_STATUS_SUCCESS == rcb->status)
9229fac68fcSPAPANI SRIKANTH 		return BSD_SUCCESS;
9239fac68fcSPAPANI SRIKANTH 	else
9249fac68fcSPAPANI SRIKANTH 		return EIO;
9259fac68fcSPAPANI SRIKANTH }
9269fac68fcSPAPANI SRIKANTH 
9271e66f787SSean Bruno /*
9281e66f787SSean Bruno  * Abort a task, task management functionality
9291e66f787SSean Bruno  */
9301e66f787SSean Bruno static int
pqisrc_scsi_abort_task(pqisrc_softstate_t * softs,union ccb * ccb)9311e66f787SSean Bruno pqisrc_scsi_abort_task(pqisrc_softstate_t *softs,  union ccb *ccb)
9321e66f787SSean Bruno {
9339fac68fcSPAPANI SRIKANTH 	rcb_t *rcb = NULL;
934*7ea28254SJohn Hall 	struct ccb_hdr *ccb_h = &ccb->ccb_h;
9359fac68fcSPAPANI SRIKANTH 	rcb_t *prcb = ccb->ccb_h.sim_priv.entries[0].ptr;
9369fac68fcSPAPANI SRIKANTH 	uint32_t tag;
9379fac68fcSPAPANI SRIKANTH 	int rval;
9381e66f787SSean Bruno 
9391e66f787SSean Bruno 	DBG_FUNC("IN\n");
9401e66f787SSean Bruno 
9411e66f787SSean Bruno 	tag = pqisrc_get_tag(&softs->taglist);
9421e66f787SSean Bruno 	rcb = &softs->rcb[tag];
9431e66f787SSean Bruno 	rcb->tag = tag;
9441e66f787SSean Bruno 
945*7ea28254SJohn Hall 	if (rcb->dvp == NULL) {
9469fac68fcSPAPANI SRIKANTH 		DBG_ERR("dvp is null, tmf type : 0x%x\n", ccb_h->func_code);
9479fac68fcSPAPANI SRIKANTH 		rval = ENXIO;
9489fac68fcSPAPANI SRIKANTH 		goto error_tmf;
9499fac68fcSPAPANI SRIKANTH 	}
9509fac68fcSPAPANI SRIKANTH 
9519fac68fcSPAPANI SRIKANTH 	rcb->tm_req = true;
9529fac68fcSPAPANI SRIKANTH 
9539fac68fcSPAPANI SRIKANTH 	rval = pqisrc_send_tmf(softs, rcb->dvp, rcb, prcb,
9541e66f787SSean Bruno 		SOP_TASK_MANAGEMENT_FUNCTION_ABORT_TASK);
9551e66f787SSean Bruno 
9569fac68fcSPAPANI SRIKANTH 	if ((rval = pqi_tmf_status_to_bsd_tmf_status(rval, rcb)) == BSD_SUCCESS)
9571e66f787SSean Bruno 		ccb->ccb_h.status = CAM_REQ_ABORTED;
9589fac68fcSPAPANI SRIKANTH 
9599fac68fcSPAPANI SRIKANTH error_tmf:
9609fac68fcSPAPANI SRIKANTH 	os_reset_rcb(rcb);
9619fac68fcSPAPANI SRIKANTH 	pqisrc_put_tag(&softs->taglist, tag);
9621e66f787SSean Bruno 
9631e66f787SSean Bruno 	DBG_FUNC("OUT rval = %d\n", rval);
9641e66f787SSean Bruno 
9651e66f787SSean Bruno 	return rval;
9661e66f787SSean Bruno }
9671e66f787SSean Bruno 
9681e66f787SSean Bruno /*
9691e66f787SSean Bruno  * Abort a taskset, task management functionality
9701e66f787SSean Bruno  */
9711e66f787SSean Bruno static int
pqisrc_scsi_abort_task_set(pqisrc_softstate_t * softs,union ccb * ccb)9721e66f787SSean Bruno pqisrc_scsi_abort_task_set(pqisrc_softstate_t *softs, union ccb *ccb)
9731e66f787SSean Bruno {
9749fac68fcSPAPANI SRIKANTH 	struct ccb_hdr *ccb_h = &ccb->ccb_h;
9751e66f787SSean Bruno 	rcb_t *rcb = NULL;
9769fac68fcSPAPANI SRIKANTH 	uint32_t tag;
9779fac68fcSPAPANI SRIKANTH 	int rval;
9781e66f787SSean Bruno 
9791e66f787SSean Bruno 	DBG_FUNC("IN\n");
9801e66f787SSean Bruno 
9811e66f787SSean Bruno 	tag = pqisrc_get_tag(&softs->taglist);
9821e66f787SSean Bruno 	rcb = &softs->rcb[tag];
9831e66f787SSean Bruno 	rcb->tag = tag;
984*7ea28254SJohn Hall 	rcb->cm_ccb = ccb;
9851e66f787SSean Bruno 
986*7ea28254SJohn Hall 	if (rcb->dvp == NULL) {
9879fac68fcSPAPANI SRIKANTH 		DBG_ERR("dvp is null, tmf type : 0x%x\n", ccb_h->func_code);
9889fac68fcSPAPANI SRIKANTH 		rval = ENXIO;
9899fac68fcSPAPANI SRIKANTH 		goto error_tmf;
9901e66f787SSean Bruno 	}
9911e66f787SSean Bruno 
9929fac68fcSPAPANI SRIKANTH 	rcb->tm_req = true;
9939fac68fcSPAPANI SRIKANTH 
9949fac68fcSPAPANI SRIKANTH 	rval = pqisrc_send_tmf(softs, rcb->dvp, rcb, NULL,
9959fac68fcSPAPANI SRIKANTH 			SOP_TASK_MANAGEMENT_FUNCTION_ABORT_TASK_SET);
9969fac68fcSPAPANI SRIKANTH 
9979fac68fcSPAPANI SRIKANTH 	rval = pqi_tmf_status_to_bsd_tmf_status(rval, rcb);
9989fac68fcSPAPANI SRIKANTH 
9999fac68fcSPAPANI SRIKANTH error_tmf:
10009fac68fcSPAPANI SRIKANTH 	os_reset_rcb(rcb);
10019fac68fcSPAPANI SRIKANTH 	pqisrc_put_tag(&softs->taglist, tag);
10021e66f787SSean Bruno 
10031e66f787SSean Bruno 	DBG_FUNC("OUT rval = %d\n", rval);
10041e66f787SSean Bruno 
10051e66f787SSean Bruno 	return rval;
10061e66f787SSean Bruno }
10071e66f787SSean Bruno 
10081e66f787SSean Bruno /*
10091e66f787SSean Bruno  * Target reset task management functionality
10101e66f787SSean Bruno  */
10111e66f787SSean Bruno static int
pqisrc_target_reset(pqisrc_softstate_t * softs,union ccb * ccb)10121e66f787SSean Bruno pqisrc_target_reset( pqisrc_softstate_t *softs,  union ccb *ccb)
10131e66f787SSean Bruno {
1014*7ea28254SJohn Hall 
1015*7ea28254SJohn Hall 	/* pqi_scsi_dev_t *devp = softs->device_list[ccb->ccb_h.target_id][ccb->ccb_h.target_lun]; */
10169fac68fcSPAPANI SRIKANTH 	struct ccb_hdr  *ccb_h = &ccb->ccb_h;
10171e66f787SSean Bruno 	rcb_t *rcb = NULL;
10189fac68fcSPAPANI SRIKANTH 	uint32_t tag;
10199fac68fcSPAPANI SRIKANTH 	int rval;
10201e66f787SSean Bruno 
1021*7ea28254SJohn Hall 	int bus, target, lun;
1022*7ea28254SJohn Hall 	int index;
1023*7ea28254SJohn Hall 
10241e66f787SSean Bruno 	DBG_FUNC("IN\n");
10251e66f787SSean Bruno 
1026*7ea28254SJohn Hall 	bus = softs->bus_id;
1027*7ea28254SJohn Hall 	target = ccb->ccb_h.target_id;
1028*7ea28254SJohn Hall 	lun = ccb->ccb_h.target_lun;
1029*7ea28254SJohn Hall 
1030*7ea28254SJohn Hall 	index = pqisrc_find_btl_list_index(softs,bus,target,lun);
1031*7ea28254SJohn Hall 	if (index == INVALID_ELEM) {
1032*7ea28254SJohn Hall 		DBG_ERR("device not found at BTL %d:%d:%d\n",bus,target,lun);
1033*7ea28254SJohn Hall 		return (-1);
1034*7ea28254SJohn Hall 	}
1035*7ea28254SJohn Hall 
1036*7ea28254SJohn Hall 	pqi_scsi_dev_t *devp = softs->dev_list[index];
10371e66f787SSean Bruno 	if (devp == NULL) {
10389fac68fcSPAPANI SRIKANTH 		DBG_ERR("bad target %d, tmf type : 0x%x\n", ccb_h->target_id, ccb_h->func_code);
1039*7ea28254SJohn Hall 		return (-1);
10401e66f787SSean Bruno 	}
10411e66f787SSean Bruno 
10421e66f787SSean Bruno 	tag = pqisrc_get_tag(&softs->taglist);
10431e66f787SSean Bruno 	rcb = &softs->rcb[tag];
10441e66f787SSean Bruno 	rcb->tag = tag;
1045*7ea28254SJohn Hall 	rcb->cm_ccb = ccb;
10469fac68fcSPAPANI SRIKANTH 
10479fac68fcSPAPANI SRIKANTH 	rcb->tm_req = true;
10489fac68fcSPAPANI SRIKANTH 
10499fac68fcSPAPANI SRIKANTH 	rval = pqisrc_send_tmf(softs, devp, rcb, NULL,
10501e66f787SSean Bruno 		SOP_TASK_MANAGEMENT_LUN_RESET);
10519fac68fcSPAPANI SRIKANTH 
10529fac68fcSPAPANI SRIKANTH 	rval = pqi_tmf_status_to_bsd_tmf_status(rval, rcb);
1053*7ea28254SJohn Hall 
10541e66f787SSean Bruno 	devp->reset_in_progress = false;
10559fac68fcSPAPANI SRIKANTH 
10569fac68fcSPAPANI SRIKANTH 	os_reset_rcb(rcb);
10579fac68fcSPAPANI SRIKANTH 	pqisrc_put_tag(&softs->taglist, tag);
10581e66f787SSean Bruno 
10591e66f787SSean Bruno 	DBG_FUNC("OUT rval = %d\n", rval);
10601e66f787SSean Bruno 
10619fac68fcSPAPANI SRIKANTH 	return rval;
10629fac68fcSPAPANI SRIKANTH 
10631e66f787SSean Bruno }
10641e66f787SSean Bruno 
10651e66f787SSean Bruno /*
10661e66f787SSean Bruno  * cam entry point of the smartpqi module.
10671e66f787SSean Bruno  */
10689fac68fcSPAPANI SRIKANTH static void
smartpqi_cam_action(struct cam_sim * sim,union ccb * ccb)10699fac68fcSPAPANI SRIKANTH smartpqi_cam_action(struct cam_sim *sim, union ccb *ccb)
10701e66f787SSean Bruno {
10711e66f787SSean Bruno 	struct pqisrc_softstate *softs = cam_sim_softc(sim);
10721e66f787SSean Bruno 	struct ccb_hdr  *ccb_h = &ccb->ccb_h;
10731e66f787SSean Bruno 
10741e66f787SSean Bruno 	DBG_FUNC("IN\n");
10751e66f787SSean Bruno 
10761e66f787SSean Bruno 	switch (ccb_h->func_code) {
10771e66f787SSean Bruno 		case XPT_SCSI_IO:
10781e66f787SSean Bruno 		{
10791e66f787SSean Bruno 			if(!pqisrc_io_start(sim, ccb)) {
10801e66f787SSean Bruno 				return;
10811e66f787SSean Bruno 			}
10821e66f787SSean Bruno 			break;
10831e66f787SSean Bruno 		}
10841e66f787SSean Bruno 		case XPT_CALC_GEOMETRY:
10851e66f787SSean Bruno 		{
10861e66f787SSean Bruno 			struct ccb_calc_geometry *ccg;
10871e66f787SSean Bruno 			ccg = &ccb->ccg;
10881e66f787SSean Bruno 			if (ccg->block_size == 0) {
10891e66f787SSean Bruno 				ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
10909fac68fcSPAPANI SRIKANTH 				ccb->ccb_h.status |= CAM_REQ_INVALID;
10911e66f787SSean Bruno 				break;
10921e66f787SSean Bruno 			}
10931e66f787SSean Bruno 			cam_calc_geometry(ccg, /* extended */ 1);
10941e66f787SSean Bruno 			ccb->ccb_h.status = CAM_REQ_CMP;
10951e66f787SSean Bruno 			break;
10961e66f787SSean Bruno 		}
10971e66f787SSean Bruno 		case XPT_PATH_INQ:
10981e66f787SSean Bruno 		{
10991e66f787SSean Bruno 			update_sim_properties(sim, &ccb->cpi);
11001e66f787SSean Bruno 			ccb->ccb_h.status = CAM_REQ_CMP;
11011e66f787SSean Bruno 			break;
11021e66f787SSean Bruno 		}
11031e66f787SSean Bruno 		case XPT_GET_TRAN_SETTINGS:
11041e66f787SSean Bruno 			get_transport_settings(softs, &ccb->cts);
11051e66f787SSean Bruno 			ccb->ccb_h.status = CAM_REQ_CMP;
11061e66f787SSean Bruno 			break;
11071e66f787SSean Bruno 		case XPT_ABORT:
11081e66f787SSean Bruno 			if(pqisrc_scsi_abort_task(softs,  ccb)) {
11091e66f787SSean Bruno 				ccb->ccb_h.status = CAM_REQ_CMP_ERR;
11101e66f787SSean Bruno 				xpt_done(ccb);
11111e66f787SSean Bruno 				DBG_ERR("Abort task failed on %d\n",
11121e66f787SSean Bruno 					ccb->ccb_h.target_id);
11131e66f787SSean Bruno 				return;
11141e66f787SSean Bruno 			}
11151e66f787SSean Bruno 			break;
11161e66f787SSean Bruno 		case XPT_TERM_IO:
11171e66f787SSean Bruno 			if (pqisrc_scsi_abort_task_set(softs,  ccb)) {
11181e66f787SSean Bruno 				ccb->ccb_h.status = CAM_REQ_CMP_ERR;
11191e66f787SSean Bruno 				DBG_ERR("Abort task set failed on %d\n",
11201e66f787SSean Bruno 					ccb->ccb_h.target_id);
11211e66f787SSean Bruno 				xpt_done(ccb);
11221e66f787SSean Bruno 				return;
11231e66f787SSean Bruno 			}
11241e66f787SSean Bruno 			break;
11251e66f787SSean Bruno 		case XPT_RESET_DEV:
11261e66f787SSean Bruno 			if(pqisrc_target_reset(softs,  ccb)) {
11271e66f787SSean Bruno 				ccb->ccb_h.status = CAM_REQ_CMP_ERR;
11281e66f787SSean Bruno 				DBG_ERR("Target reset failed on %d\n",
11291e66f787SSean Bruno 					ccb->ccb_h.target_id);
11301e66f787SSean Bruno 				xpt_done(ccb);
11311e66f787SSean Bruno 				return;
11321e66f787SSean Bruno 			} else {
11331e66f787SSean Bruno 				ccb->ccb_h.status = CAM_REQ_CMP;
11341e66f787SSean Bruno 			}
11351e66f787SSean Bruno 			break;
11361e66f787SSean Bruno 		case XPT_RESET_BUS:
11371e66f787SSean Bruno 			ccb->ccb_h.status = CAM_REQ_CMP;
11381e66f787SSean Bruno 			break;
11391e66f787SSean Bruno 		case XPT_SET_TRAN_SETTINGS:
11401e66f787SSean Bruno 			ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
11411e66f787SSean Bruno 			return;
11421e66f787SSean Bruno 		default:
11431e66f787SSean Bruno 			DBG_WARN("UNSUPPORTED FUNC CODE\n");
11441e66f787SSean Bruno 			ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
11451e66f787SSean Bruno 			break;
11461e66f787SSean Bruno 	}
11471e66f787SSean Bruno 	xpt_done(ccb);
11481e66f787SSean Bruno 
11491e66f787SSean Bruno 	DBG_FUNC("OUT\n");
11501e66f787SSean Bruno }
11511e66f787SSean Bruno 
11521e66f787SSean Bruno /*
11531e66f787SSean Bruno  * Function to poll the response, when interrupts are unavailable
11541e66f787SSean Bruno  * This also serves supporting crash dump.
11551e66f787SSean Bruno  */
11569fac68fcSPAPANI SRIKANTH static void
smartpqi_poll(struct cam_sim * sim)11579fac68fcSPAPANI SRIKANTH smartpqi_poll(struct cam_sim *sim)
11581e66f787SSean Bruno {
11591e66f787SSean Bruno 	struct pqisrc_softstate *softs = cam_sim_softc(sim);
11601e66f787SSean Bruno 	int i;
11611e66f787SSean Bruno 
11621e66f787SSean Bruno 	for (i = 1; i < softs->intr_count; i++ )
11631e66f787SSean Bruno 		pqisrc_process_response_queue(softs, i);
11641e66f787SSean Bruno }
11651e66f787SSean Bruno 
11661e66f787SSean Bruno /*
11671e66f787SSean Bruno  * Function to adjust the queue depth of a device
11681e66f787SSean Bruno  */
11699fac68fcSPAPANI SRIKANTH void
smartpqi_adjust_queue_depth(struct cam_path * path,uint32_t queue_depth)11709fac68fcSPAPANI SRIKANTH smartpqi_adjust_queue_depth(struct cam_path *path, uint32_t queue_depth)
11711e66f787SSean Bruno {
11721e66f787SSean Bruno 	struct ccb_relsim crs;
11731e66f787SSean Bruno 
1174*7ea28254SJohn Hall 	DBG_FUNC("IN\n");
11751e66f787SSean Bruno 
1176*7ea28254SJohn Hall 	memset(&crs, 0, sizeof(struct ccb_relsim));
11771e66f787SSean Bruno 	xpt_setup_ccb(&crs.ccb_h, path, 5);
11781e66f787SSean Bruno 	crs.ccb_h.func_code = XPT_REL_SIMQ;
11791e66f787SSean Bruno 	crs.ccb_h.flags = CAM_DEV_QFREEZE;
11801e66f787SSean Bruno 	crs.release_flags = RELSIM_ADJUST_OPENINGS;
11811e66f787SSean Bruno 	crs.openings = queue_depth;
11821e66f787SSean Bruno 	xpt_action((union ccb *)&crs);
11831e66f787SSean Bruno 	if(crs.ccb_h.status != CAM_REQ_CMP) {
11841e66f787SSean Bruno 		printf("XPT_REL_SIMQ failed stat=%d\n", crs.ccb_h.status);
11851e66f787SSean Bruno 	}
11861e66f787SSean Bruno 
1187*7ea28254SJohn Hall 	DBG_FUNC("OUT\n");
11881e66f787SSean Bruno }
11891e66f787SSean Bruno 
11901e66f787SSean Bruno /*
11911e66f787SSean Bruno  * Function to register async callback for setting queue depth
11921e66f787SSean Bruno  */
11931e66f787SSean Bruno static void
smartpqi_async(void * callback_arg,u_int32_t code,struct cam_path * path,void * arg)11941e66f787SSean Bruno smartpqi_async(void *callback_arg, u_int32_t code,
11951e66f787SSean Bruno 		struct cam_path *path, void *arg)
11961e66f787SSean Bruno {
11971e66f787SSean Bruno 	struct pqisrc_softstate *softs;
11981e66f787SSean Bruno 	softs = (struct pqisrc_softstate*)callback_arg;
11991e66f787SSean Bruno 
12001e66f787SSean Bruno 	DBG_FUNC("IN\n");
12011e66f787SSean Bruno 
12021e66f787SSean Bruno 	switch (code) {
12031e66f787SSean Bruno 		case AC_FOUND_DEVICE:
12041e66f787SSean Bruno 		{
12051e66f787SSean Bruno 			struct ccb_getdev *cgd;
12061e66f787SSean Bruno 			cgd = (struct ccb_getdev *)arg;
12071e66f787SSean Bruno 			if (cgd == NULL) {
12081e66f787SSean Bruno 				break;
12091e66f787SSean Bruno 			}
12101e66f787SSean Bruno 			uint32_t t_id = cgd->ccb_h.target_id;
12111e66f787SSean Bruno 
1212*7ea28254SJohn Hall 			/* if (t_id <= (PQI_CTLR_INDEX - 1)) { */
1213*7ea28254SJohn Hall 			if (t_id >= PQI_CTLR_INDEX) {
12141e66f787SSean Bruno 				if (softs != NULL) {
1215*7ea28254SJohn Hall 					/* pqi_scsi_dev_t *dvp = softs->device_list[t_id][cgd->ccb_h.target_lun]; */
1216*7ea28254SJohn Hall 					int lun = cgd->ccb_h.target_lun;
1217*7ea28254SJohn Hall 					int index = pqisrc_find_btl_list_index(softs,softs->bus_id,t_id,lun);
1218*7ea28254SJohn Hall 					if (index != INVALID_ELEM) {
1219*7ea28254SJohn Hall 						pqi_scsi_dev_t *dvp = softs->dev_list[index];
12209fac68fcSPAPANI SRIKANTH 						if (dvp == NULL) {
1221*7ea28254SJohn Hall 							DBG_ERR("Target is null, target id=%u\n", t_id);
12229fac68fcSPAPANI SRIKANTH 							break;
12239fac68fcSPAPANI SRIKANTH 						}
1224*7ea28254SJohn Hall 						smartpqi_adjust_queue_depth(path, dvp->queue_depth);
1225*7ea28254SJohn Hall 					}
12261e66f787SSean Bruno 				}
12271e66f787SSean Bruno 			}
12281e66f787SSean Bruno 			break;
12291e66f787SSean Bruno 		}
12301e66f787SSean Bruno 		default:
12311e66f787SSean Bruno 			break;
12321e66f787SSean Bruno 	}
12331e66f787SSean Bruno 
12341e66f787SSean Bruno 	DBG_FUNC("OUT\n");
12351e66f787SSean Bruno }
12361e66f787SSean Bruno 
12371e66f787SSean Bruno /*
12381e66f787SSean Bruno  * Function to register sim with CAM layer for smartpqi driver
12391e66f787SSean Bruno  */
12409fac68fcSPAPANI SRIKANTH int
register_sim(struct pqisrc_softstate * softs,int card_index)12419fac68fcSPAPANI SRIKANTH register_sim(struct pqisrc_softstate *softs, int card_index)
12421e66f787SSean Bruno {
12431e66f787SSean Bruno 	int max_transactions;
12441e66f787SSean Bruno 	union ccb   *ccb = NULL;
1245*7ea28254SJohn Hall 	cam_status status = 0;
12461e66f787SSean Bruno 	struct ccb_setasync csa;
12471e66f787SSean Bruno 	struct cam_sim *sim;
12481e66f787SSean Bruno 
12491e66f787SSean Bruno 	DBG_FUNC("IN\n");
12501e66f787SSean Bruno 
12511e66f787SSean Bruno 	max_transactions = softs->max_io_for_scsi_ml;
12521e66f787SSean Bruno 	softs->os_specific.devq = cam_simq_alloc(max_transactions);
12531e66f787SSean Bruno 	if (softs->os_specific.devq == NULL) {
12541e66f787SSean Bruno 		DBG_ERR("cam_simq_alloc failed txns = %d\n",
12551e66f787SSean Bruno 			max_transactions);
12569fac68fcSPAPANI SRIKANTH 		return ENOMEM;
12571e66f787SSean Bruno 	}
12581e66f787SSean Bruno 
12591e66f787SSean Bruno 	sim = cam_sim_alloc(smartpqi_cam_action, \
12601e66f787SSean Bruno 				smartpqi_poll, "smartpqi", softs, \
12611e66f787SSean Bruno 				card_index, &softs->os_specific.cam_lock, \
12621e66f787SSean Bruno 				1, max_transactions, softs->os_specific.devq);
12631e66f787SSean Bruno 	if (sim == NULL) {
12641e66f787SSean Bruno 		DBG_ERR("cam_sim_alloc failed txns = %d\n",
12651e66f787SSean Bruno 			max_transactions);
12661e66f787SSean Bruno 		cam_simq_free(softs->os_specific.devq);
12679fac68fcSPAPANI SRIKANTH 		return ENOMEM;
12681e66f787SSean Bruno 	}
12691e66f787SSean Bruno 
12701e66f787SSean Bruno 	softs->os_specific.sim = sim;
12711e66f787SSean Bruno 	mtx_lock(&softs->os_specific.cam_lock);
1272*7ea28254SJohn Hall 	status = xpt_bus_register(sim, softs->os_specific.pqi_dev, 0);
1273*7ea28254SJohn Hall 	if (status != CAM_SUCCESS) {
1274*7ea28254SJohn Hall 		DBG_ERR("xpt_bus_register failed status=%d\n", status);
12751e66f787SSean Bruno 		cam_sim_free(softs->os_specific.sim, FALSE);
12761e66f787SSean Bruno 		cam_simq_free(softs->os_specific.devq);
12771e66f787SSean Bruno 		mtx_unlock(&softs->os_specific.cam_lock);
12789fac68fcSPAPANI SRIKANTH 		return ENXIO;
12791e66f787SSean Bruno 	}
12801e66f787SSean Bruno 
12811e66f787SSean Bruno 	softs->os_specific.sim_registered = TRUE;
12821e66f787SSean Bruno 	ccb = xpt_alloc_ccb_nowait();
12831e66f787SSean Bruno 	if (ccb == NULL) {
12841e66f787SSean Bruno 		DBG_ERR("xpt_create_path failed\n");
12859fac68fcSPAPANI SRIKANTH 		return ENXIO;
12861e66f787SSean Bruno 	}
12871e66f787SSean Bruno 
12881e66f787SSean Bruno 	if (xpt_create_path(&ccb->ccb_h.path, NULL,
12891e66f787SSean Bruno 			cam_sim_path(softs->os_specific.sim),
12901e66f787SSean Bruno 			CAM_TARGET_WILDCARD,
12911e66f787SSean Bruno 			CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
12921e66f787SSean Bruno 		DBG_ERR("xpt_create_path failed\n");
12931e66f787SSean Bruno 		xpt_free_ccb(ccb);
12941e66f787SSean Bruno 		xpt_bus_deregister(cam_sim_path(softs->os_specific.sim));
12951e66f787SSean Bruno 		cam_sim_free(softs->os_specific.sim, TRUE);
12961e66f787SSean Bruno 		mtx_unlock(&softs->os_specific.cam_lock);
12979fac68fcSPAPANI SRIKANTH 		return ENXIO;
12981e66f787SSean Bruno 	}
12991e66f787SSean Bruno 	/*
13001e66f787SSean Bruno 	 * Callback to set the queue depth per target which is
13011e66f787SSean Bruno 	 * derived from the FW.
13021e66f787SSean Bruno 	 */
13031e66f787SSean Bruno 	softs->os_specific.path = ccb->ccb_h.path;
1304*7ea28254SJohn Hall 	memset(&csa, 0, sizeof(struct ccb_setasync));
13051e66f787SSean Bruno 	xpt_setup_ccb(&csa.ccb_h, softs->os_specific.path, 5);
13061e66f787SSean Bruno 	csa.ccb_h.func_code = XPT_SASYNC_CB;
13071e66f787SSean Bruno 	csa.event_enable = AC_FOUND_DEVICE;
13081e66f787SSean Bruno 	csa.callback = smartpqi_async;
13091e66f787SSean Bruno 	csa.callback_arg = softs;
13101e66f787SSean Bruno 	xpt_action((union ccb *)&csa);
13111e66f787SSean Bruno 	if (csa.ccb_h.status != CAM_REQ_CMP) {
13121e66f787SSean Bruno 		DBG_ERR("Unable to register smartpqi_aysnc handler: %d!\n",
13131e66f787SSean Bruno 			csa.ccb_h.status);
13141e66f787SSean Bruno 	}
13151e66f787SSean Bruno 
13161e66f787SSean Bruno 	mtx_unlock(&softs->os_specific.cam_lock);
1317*7ea28254SJohn Hall 	DBG_FUNC("OUT\n");
13189fac68fcSPAPANI SRIKANTH 
13199fac68fcSPAPANI SRIKANTH 	return BSD_SUCCESS;
13201e66f787SSean Bruno }
13211e66f787SSean Bruno 
13221e66f787SSean Bruno /*
13231e66f787SSean Bruno  * Function to deregister smartpqi sim from cam layer
13241e66f787SSean Bruno  */
13259fac68fcSPAPANI SRIKANTH void
deregister_sim(struct pqisrc_softstate * softs)13269fac68fcSPAPANI SRIKANTH deregister_sim(struct pqisrc_softstate *softs)
13271e66f787SSean Bruno {
13281e66f787SSean Bruno 	struct ccb_setasync csa;
13291e66f787SSean Bruno 
13301e66f787SSean Bruno 	DBG_FUNC("IN\n");
13311e66f787SSean Bruno 
13321e66f787SSean Bruno 	if (softs->os_specific.mtx_init) {
13331e66f787SSean Bruno 		mtx_lock(&softs->os_specific.cam_lock);
13341e66f787SSean Bruno 	}
13351e66f787SSean Bruno 
1336*7ea28254SJohn Hall 	memset(&csa, 0, sizeof(struct ccb_setasync));
13371e66f787SSean Bruno 	xpt_setup_ccb(&csa.ccb_h, softs->os_specific.path, 5);
13381e66f787SSean Bruno 	csa.ccb_h.func_code = XPT_SASYNC_CB;
13391e66f787SSean Bruno 	csa.event_enable = 0;
13401e66f787SSean Bruno 	csa.callback = smartpqi_async;
13411e66f787SSean Bruno 	csa.callback_arg = softs;
13421e66f787SSean Bruno 	xpt_action((union ccb *)&csa);
13431e66f787SSean Bruno 	xpt_free_path(softs->os_specific.path);
13441e66f787SSean Bruno 
13459fac68fcSPAPANI SRIKANTH 	if (softs->os_specific.sim) {
13461e66f787SSean Bruno 		xpt_release_simq(softs->os_specific.sim, 0);
13471e66f787SSean Bruno 		xpt_bus_deregister(cam_sim_path(softs->os_specific.sim));
13481e66f787SSean Bruno 		softs->os_specific.sim_registered = FALSE;
13491e66f787SSean Bruno 		cam_sim_free(softs->os_specific.sim, FALSE);
13501e66f787SSean Bruno 		softs->os_specific.sim = NULL;
13511e66f787SSean Bruno 	}
13529fac68fcSPAPANI SRIKANTH 
13531e66f787SSean Bruno 	if (softs->os_specific.mtx_init) {
13541e66f787SSean Bruno 		mtx_unlock(&softs->os_specific.cam_lock);
13551e66f787SSean Bruno 	}
13561e66f787SSean Bruno 	if (softs->os_specific.devq != NULL) {
13571e66f787SSean Bruno 		cam_simq_free(softs->os_specific.devq);
13581e66f787SSean Bruno 	}
13591e66f787SSean Bruno 	if (softs->os_specific.mtx_init) {
13601e66f787SSean Bruno 		mtx_destroy(&softs->os_specific.cam_lock);
13611e66f787SSean Bruno 		softs->os_specific.mtx_init = FALSE;
13621e66f787SSean Bruno 	}
13631e66f787SSean Bruno 
13641e66f787SSean Bruno 	mtx_destroy(&softs->os_specific.map_lock);
13651e66f787SSean Bruno 
13661e66f787SSean Bruno 	DBG_FUNC("OUT\n");
13671e66f787SSean Bruno }
13689fac68fcSPAPANI SRIKANTH 
13699fac68fcSPAPANI SRIKANTH void
os_rescan_target(pqisrc_softstate_t * softs,pqi_scsi_dev_t * device)13709fac68fcSPAPANI SRIKANTH os_rescan_target(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device)
13719fac68fcSPAPANI SRIKANTH {
1372*7ea28254SJohn Hall 	struct cam_path *tmppath = NULL;
13739fac68fcSPAPANI SRIKANTH 
13749fac68fcSPAPANI SRIKANTH 	DBG_FUNC("IN\n");
13759fac68fcSPAPANI SRIKANTH 
13769fac68fcSPAPANI SRIKANTH 	if(softs->os_specific.sim_registered) {
13779fac68fcSPAPANI SRIKANTH 		if (xpt_create_path(&tmppath, NULL,
13789fac68fcSPAPANI SRIKANTH 			cam_sim_path(softs->os_specific.sim),
13799fac68fcSPAPANI SRIKANTH 			device->target, device->lun) != CAM_REQ_CMP) {
13809fac68fcSPAPANI SRIKANTH 			DBG_ERR("unable to create path for async event!!! Bus: %d Target: %d Lun: %d\n",
13819fac68fcSPAPANI SRIKANTH 				device->bus, device->target, device->lun);
13829fac68fcSPAPANI SRIKANTH 			return;
13839fac68fcSPAPANI SRIKANTH 		}
13849fac68fcSPAPANI SRIKANTH 		xpt_async(AC_INQ_CHANGED, tmppath, NULL);
13859fac68fcSPAPANI SRIKANTH 		xpt_free_path(tmppath);
13869fac68fcSPAPANI SRIKANTH 	}
13879fac68fcSPAPANI SRIKANTH 
13889fac68fcSPAPANI SRIKANTH 	device->scsi_rescan = false;
13899fac68fcSPAPANI SRIKANTH 
13909fac68fcSPAPANI SRIKANTH 	DBG_FUNC("OUT\n");
13919fac68fcSPAPANI SRIKANTH }
1392