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