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