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