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