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