xref: /freebsd-13-stable/sys/dev/twa/tw_osl_cam.c (revision f8167e0404dab9ffeaca95853dd237ab7c587f82)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2004-07 Applied Micro Circuits Corporation.
5  * Copyright (c) 2004-05 Vinod Kashyap.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29 
30 /*
31  * AMCC'S 3ware driver for 9000 series storage controllers.
32  *
33  * Author: Vinod Kashyap
34  * Modifications by: Adam Radford
35  * Modifications by: Manjunath Ranganathaiah
36  */
37 
38 /*
39  * FreeBSD CAM related functions.
40  */
41 
42 #include <dev/twa/tw_osl_includes.h>
43 
44 #include <cam/cam.h>
45 #include <cam/cam_ccb.h>
46 #include <cam/cam_sim.h>
47 #include <cam/cam_xpt_sim.h>
48 #include <cam/cam_debug.h>
49 #include <cam/cam_periph.h>
50 
51 #include <cam/scsi/scsi_all.h>
52 #include <cam/scsi/scsi_message.h>
53 
54 static TW_VOID	twa_action(struct cam_sim *sim, union ccb *ccb);
55 static TW_VOID	twa_poll(struct cam_sim *sim);
56 
57 static TW_INT32	tw_osli_execute_scsi(struct tw_osli_req_context *req,
58 	union ccb *ccb);
59 
60 /*
61  * Function name:	tw_osli_cam_attach
62  * Description:		Attaches the driver to CAM.
63  *
64  * Input:		sc	-- ptr to OSL internal ctlr context
65  * Output:		None
66  * Return value:	0	-- success
67  *			non-zero-- failure
68  */
69 TW_INT32
tw_osli_cam_attach(struct twa_softc * sc)70 tw_osli_cam_attach(struct twa_softc *sc)
71 {
72 	struct cam_devq		*devq;
73 
74 	tw_osli_dbg_dprintf(3, sc, "entered");
75 
76 	/*
77 	 * Create the device queue for our SIM.
78 	 */
79 	if ((devq = cam_simq_alloc(TW_OSLI_MAX_NUM_IOS)) == NULL) {
80 		tw_osli_printf(sc, "error = %d",
81 			TW_CL_SEVERITY_ERROR_STRING,
82 			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
83 			0x2100,
84 			"Failed to create SIM device queue",
85 			ENOMEM);
86 		return(ENOMEM);
87 	}
88 
89 	/*
90 	 * Create a SIM entry.  Though we can support TW_OSLI_MAX_NUM_REQUESTS
91 	 * simultaneous requests, we claim to be able to handle only
92 	 * TW_OSLI_MAX_NUM_IOS (two less), so that we always have a request
93 	 * packet available to service ioctls and AENs.
94 	 */
95 	tw_osli_dbg_dprintf(3, sc, "Calling cam_sim_alloc");
96 	sc->sim = cam_sim_alloc(twa_action, twa_poll, "twa", sc,
97 			device_get_unit(sc->bus_dev), sc->sim_lock,
98 			TW_OSLI_MAX_NUM_IOS, 1, devq);
99 	if (sc->sim == NULL) {
100 		cam_simq_free(devq);
101 		tw_osli_printf(sc, "error = %d",
102 			TW_CL_SEVERITY_ERROR_STRING,
103 			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
104 			0x2101,
105 			"Failed to create a SIM entry",
106 			ENOMEM);
107 		return(ENOMEM);
108 	}
109 
110 	/*
111 	 * Register the bus.
112 	 */
113 	tw_osli_dbg_dprintf(3, sc, "Calling xpt_bus_register");
114 	mtx_lock(sc->sim_lock);
115 	if (xpt_bus_register(sc->sim, sc->bus_dev, 0) != CAM_SUCCESS) {
116 		cam_sim_free(sc->sim, TRUE);
117 		sc->sim = NULL; /* so cam_detach will not try to free it */
118 		tw_osli_printf(sc, "error = %d",
119 			TW_CL_SEVERITY_ERROR_STRING,
120 			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
121 			0x2102,
122 			"Failed to register the bus",
123 			ENXIO);
124 		mtx_unlock(sc->sim_lock);
125 		return(ENXIO);
126 	}
127 
128 	tw_osli_dbg_dprintf(3, sc, "Calling xpt_create_path");
129 	if (xpt_create_path(&sc->path, NULL,
130 				cam_sim_path(sc->sim),
131 				CAM_TARGET_WILDCARD,
132 				CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
133 		xpt_bus_deregister(cam_sim_path (sc->sim));
134 		/* Passing TRUE to cam_sim_free will free the devq as well. */
135 		cam_sim_free(sc->sim, TRUE);
136 		tw_osli_printf(sc, "error = %d",
137 			TW_CL_SEVERITY_ERROR_STRING,
138 			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
139 			0x2103,
140 			"Failed to create path",
141 			ENXIO);
142 		mtx_unlock(sc->sim_lock);
143 		return(ENXIO);
144 	}
145 	mtx_unlock(sc->sim_lock);
146 
147 	tw_osli_dbg_dprintf(3, sc, "exiting");
148 	return(0);
149 }
150 
151 /*
152  * Function name:	tw_osli_cam_detach
153  * Description:		Detaches the driver from CAM.
154  *
155  * Input:		sc	-- ptr to OSL internal ctlr context
156  * Output:		None
157  * Return value:	None
158  */
159 TW_VOID
tw_osli_cam_detach(struct twa_softc * sc)160 tw_osli_cam_detach(struct twa_softc *sc)
161 {
162 	tw_osli_dbg_dprintf(3, sc, "entered");
163 
164 	mtx_lock(sc->sim_lock);
165 
166 	if (sc->path)
167 		xpt_free_path(sc->path);
168 	if (sc->sim) {
169 		xpt_bus_deregister(cam_sim_path(sc->sim));
170 		/* Passing TRUE to cam_sim_free will free the devq as well. */
171 		cam_sim_free(sc->sim, TRUE);
172 	}
173 	/* It's ok have 1 hold count while destroying the mutex */
174 	mtx_destroy(sc->sim_lock);
175 }
176 
177 /*
178  * Function name:	tw_osli_execute_scsi
179  * Description:		Build a fw cmd, based on a CAM style ccb, and
180  *			send it down.
181  *
182  * Input:		req	-- ptr to OSL internal request context
183  *			ccb	-- ptr to CAM style ccb
184  * Output:		None
185  * Return value:	0	-- success
186  *			non-zero-- failure
187  */
188 TW_INT32
tw_osli_execute_scsi(struct tw_osli_req_context * req,union ccb * ccb)189 tw_osli_execute_scsi(struct tw_osli_req_context *req, union ccb *ccb)
190 {
191 	struct twa_softc		*sc = req->ctlr;
192 	struct tw_cl_req_packet		*req_pkt;
193 	struct tw_cl_scsi_req_packet	*scsi_req;
194 	struct ccb_hdr			*ccb_h = &(ccb->ccb_h);
195 	struct ccb_scsiio		*csio = &(ccb->csio);
196 	TW_INT32			error;
197 
198 	tw_osli_dbg_dprintf(10, sc, "SCSI I/O request 0x%x",
199 		csio->cdb_io.cdb_bytes[0]);
200 
201 	if (ccb_h->target_id >= TW_CL_MAX_NUM_UNITS) {
202 		tw_osli_dbg_dprintf(3, sc, "Invalid target. PTL = %x %x %jx",
203 			ccb_h->path_id, ccb_h->target_id,
204 			(uintmax_t)ccb_h->target_lun);
205 		ccb_h->status |= CAM_TID_INVALID;
206 		xpt_done(ccb);
207 		return(1);
208 	}
209 	if (ccb_h->target_lun >= TW_CL_MAX_NUM_LUNS) {
210 		tw_osli_dbg_dprintf(3, sc, "Invalid lun. PTL = %x %x %jx",
211 			ccb_h->path_id, ccb_h->target_id,
212 			(uintmax_t)ccb_h->target_lun);
213 		ccb_h->status |= CAM_LUN_INVALID;
214 		xpt_done(ccb);
215 		return(1);
216 	}
217 
218 	if(ccb_h->flags & CAM_CDB_PHYS) {
219 		tw_osli_printf(sc, "",
220 			TW_CL_SEVERITY_ERROR_STRING,
221 			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
222 			0x2105,
223 			"Physical CDB address!");
224 		ccb_h->status = CAM_REQ_INVALID;
225 		xpt_done(ccb);
226 		return(1);
227 	}
228 
229 	/*
230 	 * We are going to work on this request.  Mark it as enqueued (though
231 	 * we don't actually queue it...)
232 	 */
233 	ccb_h->status |= CAM_SIM_QUEUED;
234 
235 	if((ccb_h->flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
236 		if(ccb_h->flags & CAM_DIR_IN)
237 			req->flags |= TW_OSLI_REQ_FLAGS_DATA_IN;
238 		else
239 			req->flags |= TW_OSLI_REQ_FLAGS_DATA_OUT;
240 	}
241 
242 	/* Build the CL understood request packet for SCSI cmds. */
243 	req_pkt = &req->req_pkt;
244 	req_pkt->status = 0;
245 	req_pkt->tw_osl_callback = tw_osl_complete_io;
246 	scsi_req = &(req_pkt->gen_req_pkt.scsi_req);
247 	scsi_req->unit = ccb_h->target_id;
248 	scsi_req->lun = ccb_h->target_lun;
249 	scsi_req->sense_len = 0;
250 	scsi_req->sense_data = (TW_UINT8 *)(&csio->sense_data);
251 	scsi_req->scsi_status = 0;
252 	if(ccb_h->flags & CAM_CDB_POINTER)
253 		scsi_req->cdb = csio->cdb_io.cdb_ptr;
254 	else
255 		scsi_req->cdb = csio->cdb_io.cdb_bytes;
256 	scsi_req->cdb_len = csio->cdb_len;
257 
258 	if (csio->dxfer_len > TW_CL_MAX_IO_SIZE) {
259 		tw_osli_printf(sc, "size = %d",
260 			TW_CL_SEVERITY_ERROR_STRING,
261 			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
262 			0x2106,
263 			"I/O size too big",
264 			csio->dxfer_len);
265 		ccb_h->status = CAM_REQ_TOO_BIG;
266 		ccb_h->status &= ~CAM_SIM_QUEUED;
267 		xpt_done(ccb);
268 		return(1);
269 	}
270 	if ((ccb_h->flags & CAM_DATA_MASK) == CAM_DATA_VADDR) {
271 		if ((req->length = csio->dxfer_len) != 0) {
272 			req->data = csio->data_ptr;
273 			scsi_req->sgl_entries = 1;
274 		}
275 	} else
276 		req->flags |= TW_OSLI_REQ_FLAGS_CCB;
277 	req->deadline = tw_osl_get_local_time() + (ccb_h->timeout / 1000);
278 
279 	/*
280 	 * twa_map_load_data_callback will fill in the SGL,
281 	 * and submit the I/O.
282 	 */
283 	error = tw_osli_map_request(req);
284 	if ((error) && (req->flags & TW_OSLI_REQ_FLAGS_FAILED)) {
285 		req->deadline = 0;
286 		ccb_h->status = CAM_REQ_CMP_ERR;
287 		ccb_h->status &= ~CAM_SIM_QUEUED;
288 		xpt_done(ccb);
289 	}
290 	return(error);
291 }
292 
293 /*
294  * Function name:	twa_action
295  * Description:		Driver entry point for CAM's use.
296  *
297  * Input:		sim	-- sim corresponding to the ctlr
298  *			ccb	-- ptr to CAM request
299  * Output:		None
300  * Return value:	None
301  */
302 TW_VOID
twa_action(struct cam_sim * sim,union ccb * ccb)303 twa_action(struct cam_sim *sim, union ccb *ccb)
304 {
305 	struct twa_softc	*sc = (struct twa_softc *)cam_sim_softc(sim);
306 	struct ccb_hdr		*ccb_h = &(ccb->ccb_h);
307 
308 	switch (ccb_h->func_code) {
309 	case XPT_SCSI_IO:	/* SCSI I/O */
310 	{
311 		struct tw_osli_req_context	*req;
312 
313 		req = tw_osli_get_request(sc);
314 		if (req == NULL) {
315 			tw_osli_dbg_dprintf(2, sc, "Cannot get request pkt.");
316 			/*
317 			 * Freeze the simq to maintain ccb ordering.  The next
318 			 * ccb that gets completed will unfreeze the simq.
319 			 */
320 			ccb_h->status &= ~CAM_SIM_QUEUED;
321 			ccb_h->status |= CAM_REQUEUE_REQ;
322 			xpt_done(ccb);
323 			break;
324 		}
325 
326 		if ((tw_cl_is_reset_needed(&(req->ctlr->ctlr_handle)))) {
327 			ccb_h->status &= ~CAM_SIM_QUEUED;
328 			ccb_h->status |= CAM_REQUEUE_REQ;
329 			xpt_done(ccb);
330 			tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q);
331 			break;
332 		}
333 
334 		req->req_handle.osl_req_ctxt = req;
335 		req->req_handle.is_io = TW_CL_TRUE;
336 		req->orig_req = ccb;
337 		if (tw_osli_execute_scsi(req, ccb))
338 			tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q);
339 		break;
340 	}
341 
342 	case XPT_ABORT:
343 		tw_osli_dbg_dprintf(2, sc, "Abort request.");
344 		ccb_h->status = CAM_UA_ABORT;
345 		xpt_done(ccb);
346 		break;
347 
348 	case XPT_RESET_BUS:
349 		tw_cl_create_event(&(sc->ctlr_handle), TW_CL_FALSE,
350 			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
351 			0x2108, 0x3, TW_CL_SEVERITY_INFO_STRING,
352 			"Received Reset Bus request from CAM",
353 			" ");
354 
355 		tw_cl_set_reset_needed(&(sc->ctlr_handle));
356 		ccb_h->status = CAM_REQ_CMP;
357 		xpt_done(ccb);
358 		break;
359 
360 	case XPT_SET_TRAN_SETTINGS:
361 		tw_osli_dbg_dprintf(3, sc, "XPT_SET_TRAN_SETTINGS");
362 
363 		/*
364 		 * This command is not supported, since it's very specific
365 		 * to SCSI, and we are doing ATA.
366 		 */
367   		ccb_h->status = CAM_FUNC_NOTAVAIL;
368   		xpt_done(ccb);
369   		break;
370 
371 	case XPT_GET_TRAN_SETTINGS:
372 	{
373 		struct ccb_trans_settings	*cts = &ccb->cts;
374 		struct ccb_trans_settings_scsi *scsi =
375 		    &cts->proto_specific.scsi;
376 		struct ccb_trans_settings_spi *spi =
377 		    &cts->xport_specific.spi;
378 
379 		cts->protocol = PROTO_SCSI;
380 		cts->protocol_version = SCSI_REV_2;
381 		cts->transport = XPORT_SPI;
382 		cts->transport_version = 2;
383 
384 		spi->valid = CTS_SPI_VALID_DISC;
385 		spi->flags = CTS_SPI_FLAGS_DISC_ENB;
386 		scsi->valid = CTS_SCSI_VALID_TQ;
387 		scsi->flags = CTS_SCSI_FLAGS_TAG_ENB;
388 		tw_osli_dbg_dprintf(3, sc, "XPT_GET_TRAN_SETTINGS");
389 		ccb_h->status = CAM_REQ_CMP;
390 		xpt_done(ccb);
391 		break;
392 	}
393 
394 	case XPT_CALC_GEOMETRY:
395 		tw_osli_dbg_dprintf(3, sc, "XPT_CALC_GEOMETRY");
396 		cam_calc_geometry(&ccb->ccg, 1/* extended */);
397 		xpt_done(ccb);
398 		break;
399 
400 	case XPT_PATH_INQ:    /* Path inquiry -- get twa properties */
401 	{
402 		struct ccb_pathinq	*path_inq = &ccb->cpi;
403 
404 		tw_osli_dbg_dprintf(3, sc, "XPT_PATH_INQ request");
405 
406 		path_inq->version_num = 1;
407 		path_inq->hba_inquiry = 0;
408 		path_inq->target_sprt = 0;
409 		path_inq->hba_misc = 0;
410 		path_inq->hba_eng_cnt = 0;
411 		path_inq->max_target = TW_CL_MAX_NUM_UNITS;
412 		path_inq->max_lun = TW_CL_MAX_NUM_LUNS - 1;
413 		path_inq->unit_number = cam_sim_unit(sim);
414 		path_inq->bus_id = cam_sim_bus(sim);
415 		path_inq->initiator_id = TW_CL_MAX_NUM_UNITS;
416 		path_inq->base_transfer_speed = 100000;
417 		strlcpy(path_inq->sim_vid, "FreeBSD", SIM_IDLEN);
418 		strlcpy(path_inq->hba_vid, "3ware", HBA_IDLEN);
419 		strlcpy(path_inq->dev_name, cam_sim_name(sim), DEV_IDLEN);
420 		path_inq->transport = XPORT_SPI;
421 		path_inq->transport_version = 2;
422 		path_inq->protocol = PROTO_SCSI;
423 		path_inq->protocol_version = SCSI_REV_2;
424 		path_inq->maxio = TW_CL_MAX_IO_SIZE;
425 		ccb_h->status = CAM_REQ_CMP;
426 		xpt_done(ccb);
427 		break;
428 	}
429 
430 	default:
431 		tw_osli_dbg_dprintf(3, sc, "func_code = %x", ccb_h->func_code);
432 		ccb_h->status = CAM_REQ_INVALID;
433 		xpt_done(ccb);
434 		break;
435 	}
436 }
437 
438 /*
439  * Function name:	twa_poll
440  * Description:		Driver entry point called when interrupts are not
441  *			available.
442  *
443  * Input:		sim	-- sim corresponding to the controller
444  * Output:		None
445  * Return value:	None
446  */
447 TW_VOID
twa_poll(struct cam_sim * sim)448 twa_poll(struct cam_sim *sim)
449 {
450 	struct twa_softc *sc = (struct twa_softc *)(cam_sim_softc(sim));
451 
452 	tw_osli_dbg_dprintf(3, sc, "entering; sc = %p", sc);
453 	tw_cl_interrupt(&(sc->ctlr_handle));
454 	tw_osli_dbg_dprintf(3, sc, "exiting; sc = %p", sc);
455 }
456 
457 /*
458  * Function name:	tw_osli_request_bus_scan
459  * Description:		Requests CAM for a scan of the bus.
460  *
461  * Input:		sc	-- ptr to per ctlr structure
462  * Output:		None
463  * Return value:	0	-- success
464  *			non-zero-- failure
465  */
466 TW_INT32
tw_osli_request_bus_scan(struct twa_softc * sc)467 tw_osli_request_bus_scan(struct twa_softc *sc)
468 {
469 	union ccb	*ccb;
470 
471 	tw_osli_dbg_dprintf(3, sc, "entering");
472 
473 	/* If we get here before sc->sim is initialized, return an error. */
474 	if (!(sc->sim))
475 		return(ENXIO);
476 	if ((ccb = xpt_alloc_ccb()) == NULL)
477 		return(ENOMEM);
478 	mtx_lock(sc->sim_lock);
479 	if (xpt_create_path(&ccb->ccb_h.path, NULL, cam_sim_path(sc->sim),
480 	    CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
481 		xpt_free_ccb(ccb);
482 		mtx_unlock(sc->sim_lock);
483 		return(EIO);
484 	}
485 
486 	xpt_rescan(ccb);
487 	mtx_unlock(sc->sim_lock);
488 	return(0);
489 }
490 
491 /*
492  * Function name:	tw_osli_disallow_new_requests
493  * Description:		Calls the appropriate CAM function, so as to freeze
494  *			the flow of new requests from CAM to this controller.
495  *
496  * Input:		sc	-- ptr to OSL internal ctlr context
497  *			req_handle -- ptr to request handle sent by OSL.
498  * Output:		None
499  * Return value:	None
500  */
501 TW_VOID
tw_osli_disallow_new_requests(struct twa_softc * sc,struct tw_cl_req_handle * req_handle)502 tw_osli_disallow_new_requests(struct twa_softc *sc,
503 	struct tw_cl_req_handle *req_handle)
504 {
505 	/* Only freeze/release the simq for IOs */
506 	if (req_handle->is_io) {
507 		struct tw_osli_req_context	*req = req_handle->osl_req_ctxt;
508 		union ccb			*ccb = (union ccb *)(req->orig_req);
509 
510 		xpt_freeze_simq(sc->sim, 1);
511 		ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
512 	}
513 }
514 
515 /*
516  * Function name:	tw_osl_timeout
517  * Description:		Call to timeout().
518  *
519  * Input:		req_handle -- ptr to request handle sent by OSL.
520  * Output:		None
521  * Return value:	None
522  */
523 TW_VOID
tw_osl_timeout(struct tw_cl_req_handle * req_handle)524 tw_osl_timeout(struct tw_cl_req_handle *req_handle)
525 {
526 	struct tw_osli_req_context	*req = req_handle->osl_req_ctxt;
527 	union ccb			*ccb = (union ccb *)(req->orig_req);
528 	struct ccb_hdr			*ccb_h = &(ccb->ccb_h);
529 
530 	req->deadline = tw_osl_get_local_time() + (ccb_h->timeout / 1000);
531 }
532 
533 /*
534  * Function name:	tw_osl_untimeout
535  * Description:		Inverse of call to timeout().
536  *
537  * Input:		req_handle -- ptr to request handle sent by OSL.
538  * Output:		None
539  * Return value:	None
540  */
541 TW_VOID
tw_osl_untimeout(struct tw_cl_req_handle * req_handle)542 tw_osl_untimeout(struct tw_cl_req_handle *req_handle)
543 {
544 	struct tw_osli_req_context	*req = req_handle->osl_req_ctxt;
545 
546 	req->deadline = 0;
547 }
548 
549 /*
550  * Function name:	tw_osl_scan_bus
551  * Description:		CL calls this function to request for a bus scan.
552  *
553  * Input:		ctlr_handle	-- ptr to controller handle
554  * Output:		None
555  * Return value:	None
556  */
557 TW_VOID
tw_osl_scan_bus(struct tw_cl_ctlr_handle * ctlr_handle)558 tw_osl_scan_bus(struct tw_cl_ctlr_handle *ctlr_handle)
559 {
560 	struct twa_softc	*sc = ctlr_handle->osl_ctlr_ctxt;
561 	TW_INT32		error;
562 
563 	if ((error = tw_osli_request_bus_scan(sc)))
564 		tw_osli_printf(sc, "error = %d",
565 			TW_CL_SEVERITY_ERROR_STRING,
566 			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
567 			0x2109,
568 			"Bus scan request to CAM failed",
569 			error);
570 }
571 
572 /*
573  * Function name:	tw_osl_complete_io
574  * Description:		Called to complete CAM scsi requests.
575  *
576  * Input:		req_handle	-- ptr to request handle
577  * Output:		None
578  * Return value:	None
579  */
580 TW_VOID
tw_osl_complete_io(struct tw_cl_req_handle * req_handle)581 tw_osl_complete_io(struct tw_cl_req_handle *req_handle)
582 {
583 	struct tw_osli_req_context	*req = req_handle->osl_req_ctxt;
584 	struct tw_cl_req_packet		*req_pkt =
585 		(struct tw_cl_req_packet *)(&req->req_pkt);
586 	struct tw_cl_scsi_req_packet	*scsi_req;
587 	struct twa_softc		*sc = req->ctlr;
588 	union ccb			*ccb = (union ccb *)(req->orig_req);
589 
590 	tw_osli_dbg_dprintf(10, sc, "entering");
591 
592 	if (req->state != TW_OSLI_REQ_STATE_BUSY)
593 		tw_osli_printf(sc, "request = %p, status = %d",
594 			TW_CL_SEVERITY_ERROR_STRING,
595 			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
596 			0x210A,
597 			"Unposted command completed!!",
598 			req, req->state);
599 
600 	/*
601 	 * Remove request from the busy queue.  Just mark it complete.
602 	 * There's no need to move it into the complete queue as we are
603 	 * going to be done with it right now.
604 	 */
605 	req->state = TW_OSLI_REQ_STATE_COMPLETE;
606 	tw_osli_req_q_remove_item(req, TW_OSLI_BUSY_Q);
607 
608 	tw_osli_unmap_request(req);
609 
610 	req->deadline = 0;
611 	if (req->error_code) {
612 		/* This request never got submitted to the firmware. */
613 		if (req->error_code == EBUSY) {
614 			/*
615 			 * Cmd queue is full, or the Common Layer is out of
616 			 * resources.  The simq will already have been frozen.
617 			 * When this ccb gets completed will unfreeze the simq.
618 			 */
619 			ccb->ccb_h.status |= CAM_REQUEUE_REQ;
620 		}
621 		else if (req->error_code == EFBIG)
622 			ccb->ccb_h.status = CAM_REQ_TOO_BIG;
623 		else
624 			ccb->ccb_h.status = CAM_REQ_CMP_ERR;
625 	} else {
626 		scsi_req = &(req_pkt->gen_req_pkt.scsi_req);
627 		if (req_pkt->status == TW_CL_ERR_REQ_SUCCESS)
628 			ccb->ccb_h.status = CAM_REQ_CMP;
629 		else {
630 			if (req_pkt->status & TW_CL_ERR_REQ_INVALID_TARGET)
631 				ccb->ccb_h.status |= CAM_SEL_TIMEOUT;
632 			else if (req_pkt->status & TW_CL_ERR_REQ_INVALID_LUN)
633 				ccb->ccb_h.status |= CAM_DEV_NOT_THERE;
634 			else if (req_pkt->status & TW_CL_ERR_REQ_SCSI_ERROR)
635 				ccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
636 			else if (req_pkt->status & TW_CL_ERR_REQ_BUS_RESET)
637 				ccb->ccb_h.status |= (CAM_REQUEUE_REQ | CAM_SCSI_BUS_RESET);
638 			/*
639 			 * If none of the above errors occurred, simply
640 			 * mark completion error.
641 			 */
642 			if (ccb->ccb_h.status == 0)
643 				ccb->ccb_h.status = CAM_REQ_CMP_ERR;
644 
645 			if (req_pkt->status & TW_CL_ERR_REQ_AUTO_SENSE_VALID) {
646 				ccb->csio.sense_len = scsi_req->sense_len;
647 				ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
648 			}
649 		}
650 
651 		ccb->csio.scsi_status = scsi_req->scsi_status;
652 	}
653 
654 	ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
655 	mtx_lock(sc->sim_lock);
656 	xpt_done(ccb);
657 	mtx_unlock(sc->sim_lock);
658 	if (! req->error_code)
659 		 /* twa_action will free the request otherwise */
660 		tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q);
661 }
662