tw_osl_cam.c revision 145688
1235783Skib/*
2235783Skib * Copyright (c) 2004-05 Applied Micro Circuits Corporation.
3235783Skib * Copyright (c) 2004-05 Vinod Kashyap.
4235783Skib * All rights reserved.
5235783Skib *
6235783Skib * Redistribution and use in source and binary forms, with or without
7235783Skib * modification, are permitted provided that the following conditions
8235783Skib * are met:
9235783Skib * 1. Redistributions of source code must retain the above copyright
10235783Skib *    notice, this list of conditions and the following disclaimer.
11235783Skib * 2. Redistributions in binary form must reproduce the above copyright
12235783Skib *    notice, this list of conditions and the following disclaimer in the
13235783Skib *    documentation and/or other materials provided with the distribution.
14235783Skib *
15235783Skib * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16235783Skib * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17235783Skib * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18235783Skib * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19235783Skib * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20235783Skib * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21235783Skib * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22235783Skib * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23235783Skib * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24235783Skib * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25235783Skib * SUCH DAMAGE.
26235783Skib *
27235783Skib *	$FreeBSD: head/sys/dev/twa/tw_osl_cam.c 145688 2005-04-29 20:03:20Z vkashyap $
28235783Skib */
29235783Skib
30235783Skib/*
31235783Skib * AMCC'S 3ware driver for 9000 series storage controllers.
32235783Skib *
33235783Skib * Author: Vinod Kashyap
34235783Skib */
35235783Skib
36235783Skib
37235783Skib/*
38235783Skib * FreeBSD CAM related functions.
39235783Skib */
40235783Skib
41235783Skib
42235783Skib#include "tw_osl_includes.h"
43235783Skib
44235783Skib#include <cam/cam.h>
45235783Skib#include <cam/cam_ccb.h>
46235783Skib#include <cam/cam_sim.h>
47235783Skib#include <cam/cam_xpt_sim.h>
48235783Skib#include <cam/cam_xpt_periph.h>
49235783Skib#include <cam/cam_debug.h>
50235783Skib#include <cam/cam_periph.h>
51235783Skib
52235783Skib#include <cam/scsi/scsi_all.h>
53235783Skib#include <cam/scsi/scsi_message.h>
54235783Skib
55235783Skibstatic TW_VOID	twa_action(struct cam_sim *sim, union ccb *ccb);
56235783Skibstatic TW_VOID	twa_poll(struct cam_sim *sim);
57235783Skibstatic TW_VOID	twa_async(TW_VOID *callback_arg, TW_UINT32 code,
58235783Skib	struct cam_path *path, TW_VOID *arg);
59235783Skibstatic TW_VOID	twa_timeout(TW_VOID *arg);
60235783Skibstatic TW_VOID	twa_bus_scan_cb(struct cam_periph *periph, union ccb *ccb);
61235783Skib
62235783Skibstatic TW_INT32	tw_osli_execute_scsi(struct tw_osli_req_context *req,
63235783Skib	union ccb *ccb);
64235783Skib
65235783Skib
66235783Skib
67235783Skib/*
68235783Skib * Function name:	tw_osli_cam_attach
69235783Skib * Description:		Attaches the driver to CAM.
70235783Skib *
71235783Skib * Input:		sc	-- ptr to OSL internal ctlr context
72235783Skib * Output:		None
73235783Skib * Return value:	0	-- success
74235783Skib *			non-zero-- failure
75235783Skib */
76235783SkibTW_INT32
77235783Skibtw_osli_cam_attach(struct twa_softc *sc)
78235783Skib{
79235783Skib	struct cam_devq		*devq;
80235783Skib	struct ccb_setasync	csa;
81235783Skib	TW_INT32		error;
82235783Skib
83235783Skib	tw_osli_dbg_dprintf(3, sc, "entered");
84235783Skib
85235783Skib	/*
86235783Skib	 * Create the device queue for our SIM.
87235783Skib	 */
88235783Skib	if ((devq = cam_simq_alloc(TW_OSLI_MAX_NUM_IOS)) == NULL) {
89235783Skib		tw_osli_printf(sc, "error = %d",
90235783Skib			TW_CL_SEVERITY_ERROR_STRING,
91235783Skib			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
92235783Skib			0x2100,
93235783Skib			"Failed to create SIM device queue",
94235783Skib			ENOMEM);
95235783Skib		return(ENOMEM);
96235783Skib	}
97235783Skib
98235783Skib	/*
99235783Skib	 * Create a SIM entry.  Though we can support TW_OSLI_MAX_NUM_IOS
100235783Skib	 * simultaneous requests, we claim to be able to handle only
101235783Skib	 * (TW_OSLI_MAX_NUM_IOS - 1), so that we always have a request
102235783Skib	 * packet available to service ioctls.
103235783Skib	 */
104235783Skib	tw_osli_dbg_dprintf(3, sc, "Calling cam_sim_alloc");
105235783Skib	sc->sim = cam_sim_alloc(twa_action, twa_poll, "twa", sc,
106235783Skib			device_get_unit(sc->bus_dev),
107235783Skib			TW_OSLI_MAX_NUM_IOS - 1, 1, devq);
108235783Skib	if (sc->sim == NULL) {
109235783Skib		cam_simq_free(devq);
110235783Skib		tw_osli_printf(sc, "error = %d",
111235783Skib			TW_CL_SEVERITY_ERROR_STRING,
112235783Skib			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
113235783Skib			0x2101,
114235783Skib			"Failed to create a SIM entry",
115235783Skib			ENOMEM);
116235783Skib		return(ENOMEM);
117235783Skib	}
118235783Skib
119235783Skib	/*
120235783Skib	 * Register the bus.
121235783Skib	 */
122235783Skib	tw_osli_dbg_dprintf(3, sc, "Calling xpt_bus_register");
123235783Skib	if (xpt_bus_register(sc->sim, 0) != CAM_SUCCESS) {
124235783Skib		cam_sim_free(sc->sim, TRUE);
125235783Skib		sc->sim = NULL; /* so cam_detach will not try to free it */
126235783Skib		tw_osli_printf(sc, "error = %d",
127235783Skib			TW_CL_SEVERITY_ERROR_STRING,
128235783Skib			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
129235783Skib			0x2102,
130235783Skib			"Failed to register the bus",
131235783Skib			ENXIO);
132235783Skib		return(ENXIO);
133235783Skib	}
134235783Skib
135235783Skib	tw_osli_dbg_dprintf(3, sc, "Calling xpt_create_path");
136235783Skib	if (xpt_create_path(&sc->path, NULL,
137235783Skib				cam_sim_path(sc->sim),
138235783Skib				CAM_TARGET_WILDCARD,
139235783Skib				CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
140235783Skib		xpt_bus_deregister(cam_sim_path (sc->sim));
141235783Skib		/* Passing TRUE to cam_sim_free will free the devq as well. */
142235783Skib		cam_sim_free(sc->sim, TRUE);
143235783Skib		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		return(ENXIO);
150	}
151
152	tw_osli_dbg_dprintf(3, sc, "Calling xpt_setup_ccb");
153	xpt_setup_ccb(&csa.ccb_h, sc->path, 5);
154	csa.ccb_h.func_code = XPT_SASYNC_CB;
155	csa.event_enable = AC_FOUND_DEVICE | AC_LOST_DEVICE;
156	csa.callback = twa_async;
157	csa.callback_arg = sc;
158	xpt_action((union ccb *)&csa);
159
160	tw_osli_dbg_dprintf(3, sc, "Calling tw_osli_request_bus_scan");
161	/*
162	 * Request a bus scan, so that CAM gets to know of
163	 * the logical units that we control.
164	 */
165	if ((error = tw_osli_request_bus_scan(sc)))
166		tw_osli_printf(sc, "error = %d",
167			TW_CL_SEVERITY_ERROR_STRING,
168			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
169			0x2104,
170			"Bus scan request to CAM failed",
171			error);
172
173	tw_osli_dbg_dprintf(3, sc, "exiting");
174	return(0);
175}
176
177
178
179/*
180 * Function name:	tw_osli_cam_detach
181 * Description:		Detaches the driver from CAM.
182 *
183 * Input:		sc	-- ptr to OSL internal ctlr context
184 * Output:		None
185 * Return value:	None
186 */
187TW_VOID
188tw_osli_cam_detach(struct twa_softc *sc)
189{
190	tw_osli_dbg_dprintf(3, sc, "entered");
191
192	if (sc->path)
193		xpt_free_path(sc->path);
194	if (sc->sim) {
195		xpt_bus_deregister(cam_sim_path(sc->sim));
196		/* Passing TRUE to cam_sim_free will free the devq as well. */
197		cam_sim_free(sc->sim, TRUE);
198	}
199}
200
201
202
203/*
204 * Function name:	tw_osli_execute_scsi
205 * Description:		Build a fw cmd, based on a CAM style ccb, and
206 *			send it down.
207 *
208 * Input:		req	-- ptr to OSL internal request context
209 *			ccb	-- ptr to CAM style ccb
210 * Output:		None
211 * Return value:	0	-- success
212 *			non-zero-- failure
213 */
214TW_INT32
215tw_osli_execute_scsi(struct tw_osli_req_context *req, union ccb *ccb)
216{
217	struct twa_softc		*sc = req->ctlr;
218	struct tw_cl_req_packet		*req_pkt;
219	struct tw_cl_scsi_req_packet	*scsi_req;
220	struct ccb_hdr			*ccb_h = &(ccb->ccb_h);
221	struct ccb_scsiio		*csio = &(ccb->csio);
222	TW_INT32			error;
223
224	tw_osli_dbg_dprintf(10, sc, "SCSI I/O request 0x%x",
225		csio->cdb_io.cdb_bytes[0]);
226
227	if (ccb_h->target_id >= TW_CL_MAX_NUM_UNITS) {
228		tw_osli_dbg_dprintf(3, sc, "Invalid target. PTL = %x %x %x",
229			ccb_h->path_id, ccb_h->target_id, ccb_h->target_lun);
230		ccb_h->status |= CAM_TID_INVALID;
231		xpt_done(ccb);
232		return(1);
233	}
234	if (ccb_h->target_lun >= TW_CL_MAX_NUM_LUNS) {
235		tw_osli_dbg_dprintf(3, sc, "Invalid lun. PTL = %x %x %x",
236			ccb_h->path_id, ccb_h->target_id, 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_CMP_ERR;
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				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_CMP_ERR;
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_CMP_ERR;
321		ccb_h->status |= CAM_RELEASE_SIMQ;
322		ccb_h->status &= ~CAM_SIM_QUEUED;
323		xpt_done(ccb);
324		return(1);
325	}
326
327	ccb_h->timeout_ch = timeout(twa_timeout, req,
328		(ccb_h->timeout * hz) / 1000);
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	return(error);
335}
336
337
338
339/*
340 * Function name:	twa_action
341 * Description:		Driver entry point for CAM's use.
342 *
343 * Input:		sim	-- sim corresponding to the ctlr
344 *			ccb	-- ptr to CAM request
345 * Output:		None
346 * Return value:	None
347 */
348TW_VOID
349twa_action(struct cam_sim *sim, union ccb *ccb)
350{
351	struct twa_softc	*sc = (struct twa_softc *)cam_sim_softc(sim);
352	struct ccb_hdr		*ccb_h = &(ccb->ccb_h);
353
354	switch (ccb_h->func_code) {
355	case XPT_SCSI_IO:	/* SCSI I/O */
356	{
357		struct tw_osli_req_context	*req;
358
359		if ((sc->state & TW_OSLI_CTLR_STATE_SIMQ_FROZEN) ||
360				((req = tw_osli_get_request(sc)) == NULL)) {
361			tw_osli_dbg_dprintf(2, sc,
362				"simq frozen/Cannot get request pkt.");
363			/*
364			 * Freeze the simq to maintain ccb ordering.  The next
365			 * ccb that gets completed will unfreeze the simq.
366			 */
367			tw_osli_disallow_new_requests(sc);
368			ccb_h->status |= CAM_REQUEUE_REQ;
369			xpt_done(ccb);
370			break;
371		}
372		req->req_handle.osl_req_ctxt = req;
373		req->orig_req = ccb;
374		if (tw_osli_execute_scsi(req, ccb))
375			tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q);
376		break;
377	}
378
379	case XPT_ABORT:
380		tw_osli_dbg_dprintf(2, sc, "Abort request.");
381		ccb_h->status = CAM_UA_ABORT;
382		xpt_done(ccb);
383		break;
384
385	case XPT_RESET_BUS:
386		tw_cl_create_event(&(sc->ctlr_handle), TW_CL_TRUE,
387			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
388			0x2108, 0x3, TW_CL_SEVERITY_INFO_STRING,
389			"Received Reset Bus request from CAM",
390			" ");
391
392		if (tw_cl_reset_ctlr(&sc->ctlr_handle)) {
393			tw_cl_create_event(&(sc->ctlr_handle), TW_CL_TRUE,
394				TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
395				0x2109, 0x1, TW_CL_SEVERITY_ERROR_STRING,
396				"Failed to reset bus",
397				" ");
398			ccb_h->status = CAM_REQ_CMP_ERR;
399		}
400		else
401			ccb_h->status = CAM_REQ_CMP;
402
403		xpt_done(ccb);
404		break;
405
406	case XPT_SET_TRAN_SETTINGS:
407		tw_osli_dbg_dprintf(3, sc, "XPT_SET_TRAN_SETTINGS");
408
409		/*
410		 * This command is not supported, since it's very specific
411		 * to SCSI, and we are doing ATA.
412		 */
413  		ccb_h->status = CAM_FUNC_NOTAVAIL;
414  		xpt_done(ccb);
415  		break;
416
417	case XPT_GET_TRAN_SETTINGS:
418	{
419		struct ccb_trans_settings	*cts = &ccb->cts;
420
421		tw_osli_dbg_dprintf(3, sc, "XPT_GET_TRAN_SETTINGS");
422		cts->valid = (CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID);
423		cts->flags &= ~(CCB_TRANS_DISC_ENB | CCB_TRANS_TAG_ENB);
424		ccb_h->status = CAM_REQ_CMP;
425		xpt_done(ccb);
426		break;
427	}
428
429	case XPT_CALC_GEOMETRY:
430		tw_osli_dbg_dprintf(3, sc, "XPT_CALC_GEOMETRY");
431		cam_calc_geometry(&ccb->ccg, 1/* extended */);
432		xpt_done(ccb);
433		break;
434
435	case XPT_PATH_INQ:    /* Path inquiry -- get twa properties */
436	{
437		struct ccb_pathinq	*path_inq = &ccb->cpi;
438
439		tw_osli_dbg_dprintf(3, sc, "XPT_PATH_INQ request");
440
441		path_inq->version_num = 1;
442		path_inq->hba_inquiry = 0;
443		path_inq->target_sprt = 0;
444		path_inq->hba_misc = 0;
445		path_inq->hba_eng_cnt = 0;
446		path_inq->max_target = TW_CL_MAX_NUM_UNITS;
447		path_inq->max_lun = TW_CL_MAX_NUM_LUNS - 1;
448		path_inq->unit_number = cam_sim_unit(sim);
449		path_inq->bus_id = cam_sim_bus(sim);
450		path_inq->initiator_id = 12;
451		path_inq->base_transfer_speed = 100000;
452		strncpy(path_inq->sim_vid, "FreeBSD", SIM_IDLEN);
453		strncpy(path_inq->hba_vid, "3ware", HBA_IDLEN);
454		strncpy(path_inq->dev_name, cam_sim_name(sim), DEV_IDLEN);
455		ccb_h->status = CAM_REQ_CMP;
456		xpt_done(ccb);
457		break;
458	}
459
460	default:
461		tw_osli_dbg_dprintf(3, sc, "func_code = %x", ccb_h->func_code);
462		ccb_h->status = CAM_REQ_INVALID;
463		xpt_done(ccb);
464		break;
465	}
466}
467
468
469
470/*
471 * Function name:	twa_poll
472 * Description:		Driver entry point called when interrupts are not
473 *			available.
474 *
475 * Input:		sim	-- sim corresponding to the controller
476 * Output:		None
477 * Return value:	None
478 */
479TW_VOID
480twa_poll(struct cam_sim *sim)
481{
482	struct twa_softc *sc = (struct twa_softc *)(cam_sim_softc(sim));
483
484	tw_osli_dbg_dprintf(3, sc, "entering; sc = %p", sc);
485	/*
486	 * It's been observed that twa_poll can get called (from
487	 * dashutdown --> xpt_polled_action) even when interrupts are
488	 * active, in which case, the ISR might clear the interrupt,
489	 * leaving the call to tw_cl_interrupt below, no way of determining
490	 * that the response from firmware is ready, resulting in
491	 * tw_cl_deferred_interrupt never getting called.  To cover this case,
492	 * we will make the call to tw_cl_deferred_interrupt not dependent
493	 * on the return value from tw_cl_interrupt.
494	 */
495	tw_cl_interrupt(&(sc->ctlr_handle));
496	tw_cl_deferred_interrupt(&(sc->ctlr_handle));
497	tw_osli_dbg_dprintf(3, sc, "exiting; sc = %p", sc);
498}
499
500
501
502/*
503 * Function name:	twa_async
504 * Description:		Driver entry point for CAM to notify driver of special
505 *			events.  We don't use this for now.
506 *
507 * Input:		callback_arg	-- ptr to per ctlr structure
508 *			code		-- code associated with the event
509 *			path		-- cam path
510 *			arg		--
511 * Output:		None
512 * Return value:	0	-- success
513 *			non-zero-- failure
514 */
515TW_VOID
516twa_async(TW_VOID *callback_arg, TW_UINT32 code,
517	struct cam_path *path, TW_VOID *arg)
518{
519#ifdef TW_OSL_DEBUG
520	struct twa_softc *sc = (struct twa_softc *)callback_arg;
521#endif /* TW_OSL_DEBUG */
522
523	tw_osli_dbg_dprintf(3, sc, "sc = %p, code = %x, path = %p, arg = %p",
524		sc, code, path, arg);
525}
526
527
528
529/*
530 * Function name:	twa_timeout
531 * Description:		Driver entry point for being alerted on a request
532 *			timing out.
533 *
534 * Input:		arg	-- ptr to timed out request
535 * Output:		None
536 * Return value:	None
537 */
538static TW_VOID
539twa_timeout(TW_VOID *arg)
540{
541	struct tw_osli_req_context	*req =
542		(struct tw_osli_req_context *)arg;
543
544	tw_cl_create_event(&(req->ctlr->ctlr_handle), TW_CL_TRUE,
545		TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
546		0x210B, 0x1, TW_CL_SEVERITY_ERROR_STRING,
547		"Request timed out!",
548		"request = %p", req);
549	tw_cl_reset_ctlr(&(req->ctlr->ctlr_handle));
550}
551
552
553
554/*
555 * Function name:	tw_osli_request_bus_scan
556 * Description:		Requests CAM for a scan of the bus.
557 *
558 * Input:		sc	-- ptr to per ctlr structure
559 * Output:		None
560 * Return value:	0	-- success
561 *			non-zero-- failure
562 */
563TW_INT32
564tw_osli_request_bus_scan(struct twa_softc *sc)
565{
566	struct cam_path	*path;
567	union ccb	*ccb;
568
569	tw_osli_dbg_dprintf(3, sc, "entering");
570
571	if ((ccb = malloc(sizeof(union ccb), M_TEMP, M_WAITOK)) == NULL)
572		return(ENOMEM);
573	bzero(ccb, sizeof(union ccb));
574	if (xpt_create_path(&path, xpt_periph, cam_sim_path(sc->sim),
575		CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP)
576		return(EIO);
577
578	xpt_setup_ccb(&ccb->ccb_h, path, 5);
579	ccb->ccb_h.func_code = XPT_SCAN_BUS;
580	ccb->ccb_h.cbfcnp = twa_bus_scan_cb;
581	ccb->crcn.flags = CAM_FLAG_NONE;
582	xpt_action(ccb);
583	return(0);
584}
585
586
587
588/*
589 * Function name:	twa_bus_scan_cb
590 * Description:		Callback from CAM on a bus scan request.
591 *
592 * Input:		periph	-- we don't use this
593 *			ccb	-- bus scan request ccb that we sent to CAM
594 * Output:		None
595 * Return value:	None
596 */
597static TW_VOID
598twa_bus_scan_cb(struct cam_periph *periph, union ccb *ccb)
599{
600	tw_osli_dbg_printf(3, "entering");
601
602	if (ccb->ccb_h.status != CAM_REQ_CMP)
603		printf("cam_scan_callback: failure status = %x\n",
604			ccb->ccb_h.status);
605	else
606		tw_osli_dbg_printf(3, "success");
607
608	xpt_free_path(ccb->ccb_h.path);
609	free(ccb, M_TEMP);
610}
611
612
613
614/*
615 * Function name:	tw_osli_allow_new_requests
616 * Description:		Sets the appropriate status bits in a ccb such that,
617 *			when the ccb is completed by a call to xpt_done,
618 *			CAM knows that it's ok to unfreeze the flow of new
619 *			requests to this controller, if the flow is frozen.
620 *
621 * Input:		sc	-- ptr to OSL internal ctlr context
622 *			ccb	-- ptr to CAM request
623 * Output:		None
624 * Return value:	None
625 */
626TW_VOID
627tw_osli_allow_new_requests(struct twa_softc *sc, TW_VOID *ccb)
628{
629	((union ccb *)(ccb))->ccb_h.status |= CAM_RELEASE_SIMQ;
630	sc->state &= ~TW_OSLI_CTLR_STATE_SIMQ_FROZEN;
631}
632
633
634
635/*
636 * Function name:	tw_osli_disallow_new_requests
637 * Description:		Calls the appropriate CAM function, so as to freeze
638 *			the flow of new requests from CAM to this controller.
639 *
640 * Input:		sc	-- ptr to OSL internal ctlr context
641 * Output:		None
642 * Return value:	None
643 */
644TW_VOID
645tw_osli_disallow_new_requests(struct twa_softc *sc)
646{
647	xpt_freeze_simq(sc->sim, 1);
648	sc->state |= TW_OSLI_CTLR_STATE_SIMQ_FROZEN;
649}
650
651
652
653/*
654 * Function name:	tw_osl_scan_bus
655 * Description:		CL calls this function to request for a bus scan.
656 *
657 * Input:		ctlr_handle	-- ptr to controller handle
658 * Output:		None
659 * Return value:	None
660 */
661TW_VOID
662tw_osl_scan_bus(struct tw_cl_ctlr_handle *ctlr_handle)
663{
664	struct twa_softc	*sc = ctlr_handle->osl_ctlr_ctxt;
665	TW_INT32		error;
666
667	if ((error = tw_osli_request_bus_scan(sc)))
668		tw_osli_printf(sc, "error = %d",
669			TW_CL_SEVERITY_ERROR_STRING,
670			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
671			0x2109,
672			"Bus scan request to CAM failed",
673			error);
674}
675
676
677
678/*
679 * Function name:	tw_osl_complete_io
680 * Description:		Called to complete CAM scsi requests.
681 *
682 * Input:		req_handle	-- ptr to request handle
683 * Output:		None
684 * Return value:	None
685 */
686TW_VOID
687tw_osl_complete_io(struct tw_cl_req_handle *req_handle)
688{
689	struct tw_osli_req_context	*req = req_handle->osl_req_ctxt;
690	struct tw_cl_req_packet		*req_pkt =
691		(struct tw_cl_req_packet *)(&req->req_pkt);
692	struct tw_cl_scsi_req_packet	*scsi_req;
693	struct twa_softc		*sc = req->ctlr;
694	union ccb			*ccb = (union ccb *)(req->orig_req);
695
696	tw_osli_dbg_dprintf(10, sc, "entering");
697
698	if (req->state != TW_OSLI_REQ_STATE_BUSY)
699		tw_osli_printf(sc, "request = %p, status = %d",
700			TW_CL_SEVERITY_ERROR_STRING,
701			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
702			0x210A,
703			"Unposted command completed!!",
704			req, req->state);
705
706	/*
707	 * Remove request from the busy queue.  Just mark it complete.
708	 * There's no need to move it into the complete queue as we are
709	 * going to be done with it right now.
710	 */
711	req->state = TW_OSLI_REQ_STATE_COMPLETE;
712	tw_osli_req_q_remove_item(req, TW_OSLI_BUSY_Q);
713
714	tw_osli_unmap_request(req);
715
716	untimeout(twa_timeout, req, ccb->ccb_h.timeout_ch);
717	if (req->error_code) {
718		/* This request never got submitted to the firmware. */
719		if (req->error_code == EBUSY) {
720			/*
721			 * Cmd queue is full, or common layer is out
722			 * of resources.  Freeze the simq to maintain
723			 * ccb ordering.  The next ccb that gets
724			 * completed will unfreeze the simq.
725			 */
726			tw_osli_disallow_new_requests(req->ctlr);
727			ccb->ccb_h.status |= CAM_REQUEUE_REQ;
728		}
729		else if (req->error_code == EFBIG)
730			ccb->ccb_h.status = CAM_REQ_TOO_BIG;
731		else
732			ccb->ccb_h.status = CAM_REQ_CMP_ERR;
733	} else {
734		scsi_req = &(req_pkt->gen_req_pkt.scsi_req);
735		if (req_pkt->status == TW_CL_ERR_REQ_SUCCESS)
736			ccb->ccb_h.status = CAM_REQ_CMP;
737		else {
738			if (req_pkt->status & TW_CL_ERR_REQ_INVALID_TARGET)
739				ccb->ccb_h.status |= CAM_TID_INVALID;
740			else if (req_pkt->status & TW_CL_ERR_REQ_INVALID_LUN)
741				ccb->ccb_h.status |= CAM_LUN_INVALID;
742			else if (req_pkt->status & TW_CL_ERR_REQ_SCSI_ERROR)
743				ccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
744			else if (req_pkt->status & TW_CL_ERR_REQ_BUS_RESET)
745				ccb->ccb_h.status |= CAM_SCSI_BUS_RESET;
746			/*
747			 * If none of the above errors occurred, simply
748			 * mark completion error.
749			 */
750			if (ccb->ccb_h.status == 0)
751				ccb->ccb_h.status = CAM_REQ_CMP_ERR;
752
753			if (req_pkt->status & TW_CL_ERR_REQ_AUTO_SENSE_VALID) {
754				ccb->csio.sense_len = scsi_req->sense_len;
755				ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
756			}
757		}
758
759		ccb->csio.scsi_status = scsi_req->scsi_status;
760		/* If simq is frozen, unfreeze it. */
761		if (sc->state & TW_OSLI_CTLR_STATE_SIMQ_FROZEN)
762			tw_osli_allow_new_requests(sc, (TW_VOID *)ccb);
763	}
764
765	ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
766	xpt_done(ccb);
767	if (! req->error_code)
768		 /* twa_action will free the request otherwise */
769		tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q);
770}
771
772