tw_osl_cam.c revision 170872
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 170872 2007-06-17 05:55:54Z scottl $
28 */
29
30/*
31 * AMCC'S 3ware driver for 9000 series storage controllers.
32 *
33 * Author: Vinod Kashyap
34 * Modifications by: Adam Radford
35 */
36
37
38/*
39 * FreeBSD CAM related functions.
40 */
41
42
43#include <dev/twa/tw_osl_includes.h>
44
45#include <cam/cam.h>
46#include <cam/cam_ccb.h>
47#include <cam/cam_sim.h>
48#include <cam/cam_xpt_sim.h>
49#include <cam/cam_debug.h>
50#include <cam/cam_periph.h>
51
52#include <cam/scsi/scsi_all.h>
53#include <cam/scsi/scsi_message.h>
54
55static TW_VOID	twa_action(struct cam_sim *sim, union ccb *ccb);
56static TW_VOID	twa_poll(struct cam_sim *sim);
57static TW_VOID	twa_async(TW_VOID *callback_arg, TW_UINT32 code,
58	struct cam_path *path, TW_VOID *arg);
59static TW_VOID	twa_timeout(TW_VOID *arg);
60static TW_VOID	twa_bus_scan_cb(struct cam_periph *periph, union ccb *ccb);
61
62static TW_INT32	tw_osli_execute_scsi(struct tw_osli_req_context *req,
63	union ccb *ccb);
64
65
66
67/*
68 * Function name:	tw_osli_cam_attach
69 * Description:		Attaches the driver to CAM.
70 *
71 * Input:		sc	-- ptr to OSL internal ctlr context
72 * Output:		None
73 * Return value:	0	-- success
74 *			non-zero-- failure
75 */
76TW_INT32
77tw_osli_cam_attach(struct twa_softc *sc)
78{
79	struct cam_devq		*devq;
80	struct ccb_setasync	csa;
81	TW_INT32		error;
82
83	tw_osli_dbg_dprintf(3, sc, "entered");
84
85	/*
86	 * Create the device queue for our SIM.
87	 */
88	if ((devq = cam_simq_alloc(TW_OSLI_MAX_NUM_IOS)) == NULL) {
89		tw_osli_printf(sc, "error = %d",
90			TW_CL_SEVERITY_ERROR_STRING,
91			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
92			0x2100,
93			"Failed to create SIM device queue",
94			ENOMEM);
95		return(ENOMEM);
96	}
97
98	/*
99	 * Create a SIM entry.  Though we can support TW_OSLI_MAX_NUM_IOS
100	 * simultaneous requests, we claim to be able to handle only
101	 * (TW_OSLI_MAX_NUM_IOS - 1), so that we always have a request
102	 * packet available to service ioctls.
103	 */
104	tw_osli_dbg_dprintf(3, sc, "Calling cam_sim_alloc");
105	sc->sim = cam_sim_alloc(twa_action, twa_poll, "twa", sc,
106			device_get_unit(sc->bus_dev), &Giant,
107			TW_OSLI_MAX_NUM_IOS - 1, 1, devq);
108	if (sc->sim == NULL) {
109		cam_simq_free(devq);
110		tw_osli_printf(sc, "error = %d",
111			TW_CL_SEVERITY_ERROR_STRING,
112			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
113			0x2101,
114			"Failed to create a SIM entry",
115			ENOMEM);
116		return(ENOMEM);
117	}
118
119	/*
120	 * Register the bus.
121	 */
122	tw_osli_dbg_dprintf(3, sc, "Calling xpt_bus_register");
123	mtx_lock(&Giant);
124	if (xpt_bus_register(sc->sim, sc->bus_dev, 0) != CAM_SUCCESS) {
125		cam_sim_free(sc->sim, TRUE);
126		sc->sim = NULL; /* so cam_detach will not try to free it */
127		tw_osli_printf(sc, "error = %d",
128			TW_CL_SEVERITY_ERROR_STRING,
129			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
130			0x2102,
131			"Failed to register the bus",
132			ENXIO);
133		mtx_unlock(&Giant);
134		return(ENXIO);
135	}
136
137	tw_osli_dbg_dprintf(3, sc, "Calling xpt_create_path");
138	if (xpt_create_path(&sc->path, NULL,
139				cam_sim_path(sc->sim),
140				CAM_TARGET_WILDCARD,
141				CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
142		xpt_bus_deregister(cam_sim_path (sc->sim));
143		/* Passing TRUE to cam_sim_free will free the devq as well. */
144		cam_sim_free(sc->sim, TRUE);
145		tw_osli_printf(sc, "error = %d",
146			TW_CL_SEVERITY_ERROR_STRING,
147			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
148			0x2103,
149			"Failed to create path",
150			ENXIO);
151		mtx_unlock(&Giant);
152		return(ENXIO);
153	}
154
155	tw_osli_dbg_dprintf(3, sc, "Calling xpt_setup_ccb");
156	xpt_setup_ccb(&csa.ccb_h, sc->path, 5);
157	csa.ccb_h.func_code = XPT_SASYNC_CB;
158	csa.event_enable = AC_FOUND_DEVICE | AC_LOST_DEVICE;
159	csa.callback = twa_async;
160	csa.callback_arg = sc;
161	xpt_action((union ccb *)&csa);
162	mtx_unlock(&Giant);
163
164	tw_osli_dbg_dprintf(3, sc, "Calling tw_osli_request_bus_scan");
165	/*
166	 * Request a bus scan, so that CAM gets to know of
167	 * the logical units that we control.
168	 */
169	if ((error = tw_osli_request_bus_scan(sc)))
170		tw_osli_printf(sc, "error = %d",
171			TW_CL_SEVERITY_ERROR_STRING,
172			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
173			0x2104,
174			"Bus scan request to CAM failed",
175			error);
176
177	tw_osli_dbg_dprintf(3, sc, "exiting");
178	return(0);
179}
180
181
182
183/*
184 * Function name:	tw_osli_cam_detach
185 * Description:		Detaches the driver from CAM.
186 *
187 * Input:		sc	-- ptr to OSL internal ctlr context
188 * Output:		None
189 * Return value:	None
190 */
191TW_VOID
192tw_osli_cam_detach(struct twa_softc *sc)
193{
194	tw_osli_dbg_dprintf(3, sc, "entered");
195
196	mtx_lock(&Giant);
197	if (sc->path)
198		xpt_free_path(sc->path);
199	if (sc->sim) {
200		xpt_bus_deregister(cam_sim_path(sc->sim));
201		/* Passing TRUE to cam_sim_free will free the devq as well. */
202		cam_sim_free(sc->sim, TRUE);
203	}
204	mtx_unlock(&Giant);
205}
206
207
208
209/*
210 * Function name:	tw_osli_execute_scsi
211 * Description:		Build a fw cmd, based on a CAM style ccb, and
212 *			send it down.
213 *
214 * Input:		req	-- ptr to OSL internal request context
215 *			ccb	-- ptr to CAM style ccb
216 * Output:		None
217 * Return value:	0	-- success
218 *			non-zero-- failure
219 */
220TW_INT32
221tw_osli_execute_scsi(struct tw_osli_req_context *req, union ccb *ccb)
222{
223	struct twa_softc		*sc = req->ctlr;
224	struct tw_cl_req_packet		*req_pkt;
225	struct tw_cl_scsi_req_packet	*scsi_req;
226	struct ccb_hdr			*ccb_h = &(ccb->ccb_h);
227	struct ccb_scsiio		*csio = &(ccb->csio);
228	TW_INT32			error;
229
230	tw_osli_dbg_dprintf(10, sc, "SCSI I/O request 0x%x",
231		csio->cdb_io.cdb_bytes[0]);
232
233	if (ccb_h->target_id >= TW_CL_MAX_NUM_UNITS) {
234		tw_osli_dbg_dprintf(3, sc, "Invalid target. PTL = %x %x %x",
235			ccb_h->path_id, ccb_h->target_id, ccb_h->target_lun);
236		ccb_h->status |= CAM_TID_INVALID;
237		xpt_done(ccb);
238		return(1);
239	}
240	if (ccb_h->target_lun >= TW_CL_MAX_NUM_LUNS) {
241		tw_osli_dbg_dprintf(3, sc, "Invalid lun. PTL = %x %x %x",
242			ccb_h->path_id, ccb_h->target_id, ccb_h->target_lun);
243		ccb_h->status |= CAM_LUN_INVALID;
244		xpt_done(ccb);
245		return(1);
246	}
247
248	if(ccb_h->flags & CAM_CDB_PHYS) {
249		tw_osli_printf(sc, "",
250			TW_CL_SEVERITY_ERROR_STRING,
251			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
252			0x2105,
253			"Physical CDB address!");
254		ccb_h->status = CAM_REQ_CMP_ERR;
255		xpt_done(ccb);
256		return(1);
257	}
258
259	/*
260	 * We are going to work on this request.  Mark it as enqueued (though
261	 * we don't actually queue it...)
262	 */
263	ccb_h->status |= CAM_SIM_QUEUED;
264
265	if((ccb_h->flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
266		if(ccb_h->flags & CAM_DIR_IN)
267			req->flags |= TW_OSLI_REQ_FLAGS_DATA_IN;
268		else
269			req->flags |= TW_OSLI_REQ_FLAGS_DATA_OUT;
270	}
271
272	/* Build the CL understood request packet for SCSI cmds. */
273	req_pkt = &req->req_pkt;
274	req_pkt->status = 0;
275	req_pkt->tw_osl_callback = tw_osl_complete_io;
276	scsi_req = &(req_pkt->gen_req_pkt.scsi_req);
277	scsi_req->unit = ccb_h->target_id;
278	scsi_req->lun = ccb_h->target_lun;
279	scsi_req->sense_len = 0;
280	scsi_req->sense_data = (TW_UINT8 *)(&csio->sense_data);
281	scsi_req->scsi_status = 0;
282	if(ccb_h->flags & CAM_CDB_POINTER)
283		scsi_req->cdb = csio->cdb_io.cdb_ptr;
284	else
285		scsi_req->cdb = csio->cdb_io.cdb_bytes;
286	scsi_req->cdb_len = csio->cdb_len;
287
288	if (!(ccb_h->flags & CAM_DATA_PHYS)) {
289		/* Virtual data addresses.  Need to convert them... */
290		tw_osli_dbg_dprintf(3, sc,
291			"XPT_SCSI_IO: Single virtual address!");
292		if (!(ccb_h->flags & CAM_SCATTER_VALID)) {
293			if (csio->dxfer_len > TW_CL_MAX_IO_SIZE) {
294				tw_osli_printf(sc, "size = %d",
295					TW_CL_SEVERITY_ERROR_STRING,
296					TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
297					0x2106,
298					"I/O size too big",
299					csio->dxfer_len);
300				ccb_h->status = CAM_REQ_TOO_BIG;
301				xpt_done(ccb);
302				return(1);
303			}
304
305			if ((req->length = csio->dxfer_len)) {
306				req->data = csio->data_ptr;
307				scsi_req->sgl_entries = 1;
308			}
309		} else {
310			tw_osli_printf(sc, "",
311				TW_CL_SEVERITY_ERROR_STRING,
312				TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
313				0x2107,
314				"XPT_SCSI_IO: Got SGList");
315			ccb_h->status = CAM_REQ_CMP_ERR;
316			xpt_done(ccb);
317			return(1);
318		}
319	} else {
320		/* Data addresses are physical. */
321		tw_osli_printf(sc, "",
322			TW_CL_SEVERITY_ERROR_STRING,
323			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
324			0x2108,
325			"XPT_SCSI_IO: Physical data addresses");
326		ccb_h->status = CAM_REQ_CMP_ERR;
327		ccb_h->status |= CAM_RELEASE_SIMQ;
328		ccb_h->status &= ~CAM_SIM_QUEUED;
329		xpt_done(ccb);
330		return(1);
331	}
332
333	ccb_h->timeout_ch = timeout(twa_timeout, req,
334		(ccb_h->timeout * hz) / 1000);
335	/*
336	 * twa_map_load_data_callback will fill in the SGL,
337	 * and submit the I/O.
338	 */
339	error = tw_osli_map_request(req);
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 */
354TW_VOID
355twa_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		if ((sc->state & TW_OSLI_CTLR_STATE_SIMQ_FROZEN) ||
366				((req = tw_osli_get_request(sc)) == NULL)) {
367			tw_osli_dbg_dprintf(2, sc,
368				"simq frozen/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			tw_osli_disallow_new_requests(sc);
374			ccb_h->status |= CAM_REQUEUE_REQ;
375			xpt_done(ccb);
376			break;
377		}
378		req->req_handle.osl_req_ctxt = req;
379		req->orig_req = ccb;
380		if (tw_osli_execute_scsi(req, ccb))
381			tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q);
382		break;
383	}
384
385	case XPT_ABORT:
386		tw_osli_dbg_dprintf(2, sc, "Abort request.");
387		ccb_h->status = CAM_UA_ABORT;
388		xpt_done(ccb);
389		break;
390
391	case XPT_RESET_BUS:
392		tw_cl_create_event(&(sc->ctlr_handle), TW_CL_TRUE,
393			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
394			0x2108, 0x3, TW_CL_SEVERITY_INFO_STRING,
395			"Received Reset Bus request from CAM",
396			" ");
397
398		if (tw_cl_reset_ctlr(&sc->ctlr_handle)) {
399			tw_cl_create_event(&(sc->ctlr_handle), TW_CL_TRUE,
400				TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
401				0x2109, 0x1, TW_CL_SEVERITY_ERROR_STRING,
402				"Failed to reset bus",
403				" ");
404			ccb_h->status = CAM_REQ_CMP_ERR;
405		}
406		else
407			ccb_h->status = CAM_REQ_CMP;
408
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		ccb_h->status = CAM_REQ_CMP;
477		xpt_done(ccb);
478		break;
479	}
480
481	default:
482		tw_osli_dbg_dprintf(3, sc, "func_code = %x", ccb_h->func_code);
483		ccb_h->status = CAM_REQ_INVALID;
484		xpt_done(ccb);
485		break;
486	}
487}
488
489
490
491/*
492 * Function name:	twa_poll
493 * Description:		Driver entry point called when interrupts are not
494 *			available.
495 *
496 * Input:		sim	-- sim corresponding to the controller
497 * Output:		None
498 * Return value:	None
499 */
500TW_VOID
501twa_poll(struct cam_sim *sim)
502{
503	struct twa_softc *sc = (struct twa_softc *)(cam_sim_softc(sim));
504
505	tw_osli_dbg_dprintf(3, sc, "entering; sc = %p", sc);
506	/*
507	 * It's been observed that twa_poll can get called (from
508	 * dashutdown --> xpt_polled_action) even when interrupts are
509	 * active, in which case, the ISR might clear the interrupt,
510	 * leaving the call to tw_cl_interrupt below, no way of determining
511	 * that the response from firmware is ready, resulting in
512	 * tw_cl_deferred_interrupt never getting called.  To cover this case,
513	 * we will make the call to tw_cl_deferred_interrupt not dependent
514	 * on the return value from tw_cl_interrupt.
515	 */
516	tw_cl_interrupt(&(sc->ctlr_handle));
517	tw_cl_deferred_interrupt(&(sc->ctlr_handle));
518	tw_osli_dbg_dprintf(3, sc, "exiting; sc = %p", sc);
519}
520
521
522
523/*
524 * Function name:	twa_async
525 * Description:		Driver entry point for CAM to notify driver of special
526 *			events.  We don't use this for now.
527 *
528 * Input:		callback_arg	-- ptr to per ctlr structure
529 *			code		-- code associated with the event
530 *			path		-- cam path
531 *			arg		--
532 * Output:		None
533 * Return value:	0	-- success
534 *			non-zero-- failure
535 */
536TW_VOID
537twa_async(TW_VOID *callback_arg, TW_UINT32 code,
538	struct cam_path *path, TW_VOID *arg)
539{
540#ifdef TW_OSL_DEBUG
541	struct twa_softc *sc = (struct twa_softc *)callback_arg;
542#endif /* TW_OSL_DEBUG */
543
544	tw_osli_dbg_dprintf(3, sc, "sc = %p, code = %x, path = %p, arg = %p",
545		sc, code, path, arg);
546}
547
548
549
550/*
551 * Function name:	twa_timeout
552 * Description:		Driver entry point for being alerted on a request
553 *			timing out.
554 *
555 * Input:		arg	-- ptr to timed out request
556 * Output:		None
557 * Return value:	None
558 */
559static TW_VOID
560twa_timeout(TW_VOID *arg)
561{
562	struct tw_osli_req_context	*req =
563		(struct tw_osli_req_context *)arg;
564
565	tw_cl_create_event(&(req->ctlr->ctlr_handle), TW_CL_TRUE,
566		TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
567		0x210B, 0x1, TW_CL_SEVERITY_ERROR_STRING,
568		"Request timed out!",
569		"request = %p", req);
570	tw_cl_reset_ctlr(&(req->ctlr->ctlr_handle));
571}
572
573
574
575/*
576 * Function name:	tw_osli_request_bus_scan
577 * Description:		Requests CAM for a scan of the bus.
578 *
579 * Input:		sc	-- ptr to per ctlr structure
580 * Output:		None
581 * Return value:	0	-- success
582 *			non-zero-- failure
583 */
584TW_INT32
585tw_osli_request_bus_scan(struct twa_softc *sc)
586{
587	struct cam_path	*path;
588	union ccb	*ccb;
589
590	tw_osli_dbg_dprintf(3, sc, "entering");
591
592	/* If we get here before sc->sim is initialized, return an error. */
593	if (!(sc->sim))
594		return(ENXIO);
595	if ((ccb = malloc(sizeof(union ccb), M_TEMP, M_WAITOK)) == NULL)
596		return(ENOMEM);
597	bzero(ccb, sizeof(union ccb));
598	mtx_lock(&Giant);
599	if (xpt_create_path(&path, xpt_periph, cam_sim_path(sc->sim),
600			    CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
601		free(ccb, M_TEMP);
602		mtx_unlock(&Giant);
603		return(EIO);
604	}
605
606	xpt_setup_ccb(&ccb->ccb_h, path, 5);
607	ccb->ccb_h.func_code = XPT_SCAN_BUS;
608	ccb->ccb_h.cbfcnp = twa_bus_scan_cb;
609	ccb->crcn.flags = CAM_FLAG_NONE;
610	xpt_action(ccb);
611	mtx_unlock(&Giant);
612	return(0);
613}
614
615
616
617/*
618 * Function name:	twa_bus_scan_cb
619 * Description:		Callback from CAM on a bus scan request.
620 *
621 * Input:		periph	-- we don't use this
622 *			ccb	-- bus scan request ccb that we sent to CAM
623 * Output:		None
624 * Return value:	None
625 */
626static TW_VOID
627twa_bus_scan_cb(struct cam_periph *periph, union ccb *ccb)
628{
629	tw_osli_dbg_printf(3, "entering");
630
631	if (ccb->ccb_h.status != CAM_REQ_CMP)
632		printf("cam_scan_callback: failure status = %x\n",
633			ccb->ccb_h.status);
634	else
635		tw_osli_dbg_printf(3, "success");
636
637	xpt_free_path(ccb->ccb_h.path);
638	free(ccb, M_TEMP);
639}
640
641
642
643/*
644 * Function name:	tw_osli_allow_new_requests
645 * Description:		Sets the appropriate status bits in a ccb such that,
646 *			when the ccb is completed by a call to xpt_done,
647 *			CAM knows that it's ok to unfreeze the flow of new
648 *			requests to this controller, if the flow is frozen.
649 *
650 * Input:		sc	-- ptr to OSL internal ctlr context
651 *			ccb	-- ptr to CAM request
652 * Output:		None
653 * Return value:	None
654 */
655TW_VOID
656tw_osli_allow_new_requests(struct twa_softc *sc, TW_VOID *ccb)
657{
658	((union ccb *)(ccb))->ccb_h.status |= CAM_RELEASE_SIMQ;
659	sc->state &= ~TW_OSLI_CTLR_STATE_SIMQ_FROZEN;
660}
661
662
663
664/*
665 * Function name:	tw_osli_disallow_new_requests
666 * Description:		Calls the appropriate CAM function, so as to freeze
667 *			the flow of new requests from CAM to this controller.
668 *
669 * Input:		sc	-- ptr to OSL internal ctlr context
670 * Output:		None
671 * Return value:	None
672 */
673TW_VOID
674tw_osli_disallow_new_requests(struct twa_softc *sc)
675{
676	mtx_lock(&Giant);
677	xpt_freeze_simq(sc->sim, 1);
678	mtx_unlock(&Giant);
679	sc->state |= TW_OSLI_CTLR_STATE_SIMQ_FROZEN;
680}
681
682
683
684/*
685 * Function name:	tw_osl_ctlr_busy
686 * Description:		CL calls this function on cmd queue full or otherwise,
687 *			when it is too busy to accept new requests.
688 *
689 * Input:		ctlr_handle	-- ptr to controller handle
690 *			req_handle	-- ptr to request handle sent by OSL.
691 * Output:		None
692 * Return value:	None
693 */
694TW_VOID
695tw_osl_ctlr_busy(struct tw_cl_ctlr_handle *ctlr_handle,
696	struct tw_cl_req_handle *req_handle)
697{
698	tw_osli_disallow_new_requests(ctlr_handle->osl_ctlr_ctxt);
699}
700
701
702
703/*
704 * Function name:	tw_osl_scan_bus
705 * Description:		CL calls this function to request for a bus scan.
706 *
707 * Input:		ctlr_handle	-- ptr to controller handle
708 * Output:		None
709 * Return value:	None
710 */
711TW_VOID
712tw_osl_scan_bus(struct tw_cl_ctlr_handle *ctlr_handle)
713{
714	struct twa_softc	*sc = ctlr_handle->osl_ctlr_ctxt;
715	TW_INT32		error;
716
717	if ((error = tw_osli_request_bus_scan(sc)))
718		tw_osli_printf(sc, "error = %d",
719			TW_CL_SEVERITY_ERROR_STRING,
720			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
721			0x2109,
722			"Bus scan request to CAM failed",
723			error);
724}
725
726
727
728/*
729 * Function name:	tw_osl_complete_io
730 * Description:		Called to complete CAM scsi requests.
731 *
732 * Input:		req_handle	-- ptr to request handle
733 * Output:		None
734 * Return value:	None
735 */
736TW_VOID
737tw_osl_complete_io(struct tw_cl_req_handle *req_handle)
738{
739	struct tw_osli_req_context	*req = req_handle->osl_req_ctxt;
740	struct tw_cl_req_packet		*req_pkt =
741		(struct tw_cl_req_packet *)(&req->req_pkt);
742	struct tw_cl_scsi_req_packet	*scsi_req;
743	struct twa_softc		*sc = req->ctlr;
744	union ccb			*ccb = (union ccb *)(req->orig_req);
745
746	tw_osli_dbg_dprintf(10, sc, "entering");
747
748	if (req->state != TW_OSLI_REQ_STATE_BUSY)
749		tw_osli_printf(sc, "request = %p, status = %d",
750			TW_CL_SEVERITY_ERROR_STRING,
751			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
752			0x210A,
753			"Unposted command completed!!",
754			req, req->state);
755
756	/*
757	 * Remove request from the busy queue.  Just mark it complete.
758	 * There's no need to move it into the complete queue as we are
759	 * going to be done with it right now.
760	 */
761	req->state = TW_OSLI_REQ_STATE_COMPLETE;
762	tw_osli_req_q_remove_item(req, TW_OSLI_BUSY_Q);
763
764	tw_osli_unmap_request(req);
765
766	untimeout(twa_timeout, req, ccb->ccb_h.timeout_ch);
767	if (req->error_code) {
768		/* This request never got submitted to the firmware. */
769		if (req->error_code == EBUSY) {
770			/*
771			 * Cmd queue is full, or the Common Layer is out of
772			 * resources.  The simq will already have been frozen
773			 * by CL's call to tw_osl_ctlr_busy, and this will
774			 * maintain ccb ordering.  The next ccb that gets
775			 * completed will unfreeze the simq.
776			 */
777			ccb->ccb_h.status |= CAM_REQUEUE_REQ;
778		}
779		else if (req->error_code == EFBIG)
780			ccb->ccb_h.status = CAM_REQ_TOO_BIG;
781		else
782			ccb->ccb_h.status = CAM_REQ_CMP_ERR;
783	} else {
784		scsi_req = &(req_pkt->gen_req_pkt.scsi_req);
785		if (req_pkt->status == TW_CL_ERR_REQ_SUCCESS)
786			ccb->ccb_h.status = CAM_REQ_CMP;
787		else {
788			if (req_pkt->status & TW_CL_ERR_REQ_INVALID_TARGET)
789				ccb->ccb_h.status |= CAM_TID_INVALID;
790			else if (req_pkt->status & TW_CL_ERR_REQ_INVALID_LUN)
791				ccb->ccb_h.status |= CAM_LUN_INVALID;
792			else if (req_pkt->status & TW_CL_ERR_REQ_SCSI_ERROR)
793				ccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
794			else if (req_pkt->status & TW_CL_ERR_REQ_BUS_RESET)
795				ccb->ccb_h.status |= CAM_SCSI_BUS_RESET;
796			/*
797			 * If none of the above errors occurred, simply
798			 * mark completion error.
799			 */
800			if (ccb->ccb_h.status == 0)
801				ccb->ccb_h.status = CAM_REQ_CMP_ERR;
802
803			if (req_pkt->status & TW_CL_ERR_REQ_AUTO_SENSE_VALID) {
804				ccb->csio.sense_len = scsi_req->sense_len;
805				ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
806			}
807		}
808
809		ccb->csio.scsi_status = scsi_req->scsi_status;
810		/* If simq is frozen, unfreeze it. */
811		if (sc->state & TW_OSLI_CTLR_STATE_SIMQ_FROZEN)
812			tw_osli_allow_new_requests(sc, (TW_VOID *)ccb);
813	}
814
815	ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
816	xpt_done(ccb);
817	if (! req->error_code)
818		 /* twa_action will free the request otherwise */
819		tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q);
820}
821
822