tw_osl_cam.c revision 163896
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 163896 2006-11-02 00:54:38Z 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		struct ccb_trans_settings_scsi *scsi =
424		    &cts->proto_specific.scsi;
425		struct ccb_trans_settings_spi *spi =
426		    &cts->xport_specific.spi;
427
428		cts->protocol = PROTO_SCSI;
429		cts->protocol_version = SCSI_REV_2;
430		cts->transport = XPORT_SPI;
431		cts->transport_version = 2;
432
433		spi->valid = CTS_SPI_VALID_DISC;
434		spi->flags = CTS_SPI_FLAGS_DISC_ENB;
435		scsi->valid = CTS_SCSI_VALID_TQ;
436		scsi->flags = CTS_SCSI_FLAGS_TAG_ENB;
437		tw_osli_dbg_dprintf(3, sc, "XPT_GET_TRAN_SETTINGS");
438		ccb_h->status = CAM_REQ_CMP;
439		xpt_done(ccb);
440		break;
441	}
442
443	case XPT_CALC_GEOMETRY:
444		tw_osli_dbg_dprintf(3, sc, "XPT_CALC_GEOMETRY");
445		cam_calc_geometry(&ccb->ccg, 1/* extended */);
446		xpt_done(ccb);
447		break;
448
449	case XPT_PATH_INQ:    /* Path inquiry -- get twa properties */
450	{
451		struct ccb_pathinq	*path_inq = &ccb->cpi;
452
453		tw_osli_dbg_dprintf(3, sc, "XPT_PATH_INQ request");
454
455		path_inq->version_num = 1;
456		path_inq->hba_inquiry = 0;
457		path_inq->target_sprt = 0;
458		path_inq->hba_misc = 0;
459		path_inq->hba_eng_cnt = 0;
460		path_inq->max_target = TW_CL_MAX_NUM_UNITS;
461		path_inq->max_lun = TW_CL_MAX_NUM_LUNS - 1;
462		path_inq->unit_number = cam_sim_unit(sim);
463		path_inq->bus_id = cam_sim_bus(sim);
464		path_inq->initiator_id = TW_CL_MAX_NUM_UNITS;
465		path_inq->base_transfer_speed = 100000;
466		strncpy(path_inq->sim_vid, "FreeBSD", SIM_IDLEN);
467		strncpy(path_inq->hba_vid, "3ware", HBA_IDLEN);
468		strncpy(path_inq->dev_name, cam_sim_name(sim), DEV_IDLEN);
469                path_inq->transport = XPORT_SPI;
470                path_inq->transport_version = 2;
471                path_inq->protocol = PROTO_SCSI;
472                path_inq->protocol_version = SCSI_REV_2;
473		ccb_h->status = CAM_REQ_CMP;
474		xpt_done(ccb);
475		break;
476	}
477
478	default:
479		tw_osli_dbg_dprintf(3, sc, "func_code = %x", ccb_h->func_code);
480		ccb_h->status = CAM_REQ_INVALID;
481		xpt_done(ccb);
482		break;
483	}
484}
485
486
487
488/*
489 * Function name:	twa_poll
490 * Description:		Driver entry point called when interrupts are not
491 *			available.
492 *
493 * Input:		sim	-- sim corresponding to the controller
494 * Output:		None
495 * Return value:	None
496 */
497TW_VOID
498twa_poll(struct cam_sim *sim)
499{
500	struct twa_softc *sc = (struct twa_softc *)(cam_sim_softc(sim));
501
502	tw_osli_dbg_dprintf(3, sc, "entering; sc = %p", sc);
503	/*
504	 * It's been observed that twa_poll can get called (from
505	 * dashutdown --> xpt_polled_action) even when interrupts are
506	 * active, in which case, the ISR might clear the interrupt,
507	 * leaving the call to tw_cl_interrupt below, no way of determining
508	 * that the response from firmware is ready, resulting in
509	 * tw_cl_deferred_interrupt never getting called.  To cover this case,
510	 * we will make the call to tw_cl_deferred_interrupt not dependent
511	 * on the return value from tw_cl_interrupt.
512	 */
513	tw_cl_interrupt(&(sc->ctlr_handle));
514	tw_cl_deferred_interrupt(&(sc->ctlr_handle));
515	tw_osli_dbg_dprintf(3, sc, "exiting; sc = %p", sc);
516}
517
518
519
520/*
521 * Function name:	twa_async
522 * Description:		Driver entry point for CAM to notify driver of special
523 *			events.  We don't use this for now.
524 *
525 * Input:		callback_arg	-- ptr to per ctlr structure
526 *			code		-- code associated with the event
527 *			path		-- cam path
528 *			arg		--
529 * Output:		None
530 * Return value:	0	-- success
531 *			non-zero-- failure
532 */
533TW_VOID
534twa_async(TW_VOID *callback_arg, TW_UINT32 code,
535	struct cam_path *path, TW_VOID *arg)
536{
537#ifdef TW_OSL_DEBUG
538	struct twa_softc *sc = (struct twa_softc *)callback_arg;
539#endif /* TW_OSL_DEBUG */
540
541	tw_osli_dbg_dprintf(3, sc, "sc = %p, code = %x, path = %p, arg = %p",
542		sc, code, path, arg);
543}
544
545
546
547/*
548 * Function name:	twa_timeout
549 * Description:		Driver entry point for being alerted on a request
550 *			timing out.
551 *
552 * Input:		arg	-- ptr to timed out request
553 * Output:		None
554 * Return value:	None
555 */
556static TW_VOID
557twa_timeout(TW_VOID *arg)
558{
559	struct tw_osli_req_context	*req =
560		(struct tw_osli_req_context *)arg;
561
562	tw_cl_create_event(&(req->ctlr->ctlr_handle), TW_CL_TRUE,
563		TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
564		0x210B, 0x1, TW_CL_SEVERITY_ERROR_STRING,
565		"Request timed out!",
566		"request = %p", req);
567	tw_cl_reset_ctlr(&(req->ctlr->ctlr_handle));
568}
569
570
571
572/*
573 * Function name:	tw_osli_request_bus_scan
574 * Description:		Requests CAM for a scan of the bus.
575 *
576 * Input:		sc	-- ptr to per ctlr structure
577 * Output:		None
578 * Return value:	0	-- success
579 *			non-zero-- failure
580 */
581TW_INT32
582tw_osli_request_bus_scan(struct twa_softc *sc)
583{
584	struct cam_path	*path;
585	union ccb	*ccb;
586
587	tw_osli_dbg_dprintf(3, sc, "entering");
588
589	/* If we get here before sc->sim is initialized, return an error. */
590	if (!(sc->sim))
591		return(ENXIO);
592	if ((ccb = malloc(sizeof(union ccb), M_TEMP, M_WAITOK)) == NULL)
593		return(ENOMEM);
594	bzero(ccb, sizeof(union ccb));
595	mtx_lock(&Giant);
596	if (xpt_create_path(&path, xpt_periph, cam_sim_path(sc->sim),
597		CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP)
598		return(EIO);
599
600	xpt_setup_ccb(&ccb->ccb_h, path, 5);
601	ccb->ccb_h.func_code = XPT_SCAN_BUS;
602	ccb->ccb_h.cbfcnp = twa_bus_scan_cb;
603	ccb->crcn.flags = CAM_FLAG_NONE;
604	xpt_action(ccb);
605	mtx_unlock(&Giant);
606	return(0);
607}
608
609
610
611/*
612 * Function name:	twa_bus_scan_cb
613 * Description:		Callback from CAM on a bus scan request.
614 *
615 * Input:		periph	-- we don't use this
616 *			ccb	-- bus scan request ccb that we sent to CAM
617 * Output:		None
618 * Return value:	None
619 */
620static TW_VOID
621twa_bus_scan_cb(struct cam_periph *periph, union ccb *ccb)
622{
623	tw_osli_dbg_printf(3, "entering");
624
625	if (ccb->ccb_h.status != CAM_REQ_CMP)
626		printf("cam_scan_callback: failure status = %x\n",
627			ccb->ccb_h.status);
628	else
629		tw_osli_dbg_printf(3, "success");
630
631	xpt_free_path(ccb->ccb_h.path);
632	free(ccb, M_TEMP);
633}
634
635
636
637/*
638 * Function name:	tw_osli_allow_new_requests
639 * Description:		Sets the appropriate status bits in a ccb such that,
640 *			when the ccb is completed by a call to xpt_done,
641 *			CAM knows that it's ok to unfreeze the flow of new
642 *			requests to this controller, if the flow is frozen.
643 *
644 * Input:		sc	-- ptr to OSL internal ctlr context
645 *			ccb	-- ptr to CAM request
646 * Output:		None
647 * Return value:	None
648 */
649TW_VOID
650tw_osli_allow_new_requests(struct twa_softc *sc, TW_VOID *ccb)
651{
652	((union ccb *)(ccb))->ccb_h.status |= CAM_RELEASE_SIMQ;
653	sc->state &= ~TW_OSLI_CTLR_STATE_SIMQ_FROZEN;
654}
655
656
657
658/*
659 * Function name:	tw_osli_disallow_new_requests
660 * Description:		Calls the appropriate CAM function, so as to freeze
661 *			the flow of new requests from CAM to this controller.
662 *
663 * Input:		sc	-- ptr to OSL internal ctlr context
664 * Output:		None
665 * Return value:	None
666 */
667TW_VOID
668tw_osli_disallow_new_requests(struct twa_softc *sc)
669{
670	mtx_lock(&Giant);
671	xpt_freeze_simq(sc->sim, 1);
672	mtx_unlock(&Giant);
673	sc->state |= TW_OSLI_CTLR_STATE_SIMQ_FROZEN;
674}
675
676
677
678/*
679 * Function name:	tw_osl_ctlr_busy
680 * Description:		CL calls this function on cmd queue full or otherwise,
681 *			when it is too busy to accept new requests.
682 *
683 * Input:		ctlr_handle	-- ptr to controller handle
684 *			req_handle	-- ptr to request handle sent by OSL.
685 * Output:		None
686 * Return value:	None
687 */
688TW_VOID
689tw_osl_ctlr_busy(struct tw_cl_ctlr_handle *ctlr_handle,
690	struct tw_cl_req_handle *req_handle)
691{
692	tw_osli_disallow_new_requests(ctlr_handle->osl_ctlr_ctxt);
693}
694
695
696
697/*
698 * Function name:	tw_osl_scan_bus
699 * Description:		CL calls this function to request for a bus scan.
700 *
701 * Input:		ctlr_handle	-- ptr to controller handle
702 * Output:		None
703 * Return value:	None
704 */
705TW_VOID
706tw_osl_scan_bus(struct tw_cl_ctlr_handle *ctlr_handle)
707{
708	struct twa_softc	*sc = ctlr_handle->osl_ctlr_ctxt;
709	TW_INT32		error;
710
711	if ((error = tw_osli_request_bus_scan(sc)))
712		tw_osli_printf(sc, "error = %d",
713			TW_CL_SEVERITY_ERROR_STRING,
714			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
715			0x2109,
716			"Bus scan request to CAM failed",
717			error);
718}
719
720
721
722/*
723 * Function name:	tw_osl_complete_io
724 * Description:		Called to complete CAM scsi requests.
725 *
726 * Input:		req_handle	-- ptr to request handle
727 * Output:		None
728 * Return value:	None
729 */
730TW_VOID
731tw_osl_complete_io(struct tw_cl_req_handle *req_handle)
732{
733	struct tw_osli_req_context	*req = req_handle->osl_req_ctxt;
734	struct tw_cl_req_packet		*req_pkt =
735		(struct tw_cl_req_packet *)(&req->req_pkt);
736	struct tw_cl_scsi_req_packet	*scsi_req;
737	struct twa_softc		*sc = req->ctlr;
738	union ccb			*ccb = (union ccb *)(req->orig_req);
739
740	tw_osli_dbg_dprintf(10, sc, "entering");
741
742	if (req->state != TW_OSLI_REQ_STATE_BUSY)
743		tw_osli_printf(sc, "request = %p, status = %d",
744			TW_CL_SEVERITY_ERROR_STRING,
745			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
746			0x210A,
747			"Unposted command completed!!",
748			req, req->state);
749
750	/*
751	 * Remove request from the busy queue.  Just mark it complete.
752	 * There's no need to move it into the complete queue as we are
753	 * going to be done with it right now.
754	 */
755	req->state = TW_OSLI_REQ_STATE_COMPLETE;
756	tw_osli_req_q_remove_item(req, TW_OSLI_BUSY_Q);
757
758	tw_osli_unmap_request(req);
759
760	untimeout(twa_timeout, req, ccb->ccb_h.timeout_ch);
761	if (req->error_code) {
762		/* This request never got submitted to the firmware. */
763		if (req->error_code == EBUSY) {
764			/*
765			 * Cmd queue is full, or the Common Layer is out of
766			 * resources.  The simq will already have been frozen
767			 * by CL's call to tw_osl_ctlr_busy, and this will
768			 * maintain ccb ordering.  The next ccb that gets
769			 * completed will unfreeze the simq.
770			 */
771			ccb->ccb_h.status |= CAM_REQUEUE_REQ;
772		}
773		else if (req->error_code == EFBIG)
774			ccb->ccb_h.status = CAM_REQ_TOO_BIG;
775		else
776			ccb->ccb_h.status = CAM_REQ_CMP_ERR;
777	} else {
778		scsi_req = &(req_pkt->gen_req_pkt.scsi_req);
779		if (req_pkt->status == TW_CL_ERR_REQ_SUCCESS)
780			ccb->ccb_h.status = CAM_REQ_CMP;
781		else {
782			if (req_pkt->status & TW_CL_ERR_REQ_INVALID_TARGET)
783				ccb->ccb_h.status |= CAM_TID_INVALID;
784			else if (req_pkt->status & TW_CL_ERR_REQ_INVALID_LUN)
785				ccb->ccb_h.status |= CAM_LUN_INVALID;
786			else if (req_pkt->status & TW_CL_ERR_REQ_SCSI_ERROR)
787				ccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
788			else if (req_pkt->status & TW_CL_ERR_REQ_BUS_RESET)
789				ccb->ccb_h.status |= CAM_SCSI_BUS_RESET;
790			/*
791			 * If none of the above errors occurred, simply
792			 * mark completion error.
793			 */
794			if (ccb->ccb_h.status == 0)
795				ccb->ccb_h.status = CAM_REQ_CMP_ERR;
796
797			if (req_pkt->status & TW_CL_ERR_REQ_AUTO_SENSE_VALID) {
798				ccb->csio.sense_len = scsi_req->sense_len;
799				ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
800			}
801		}
802
803		ccb->csio.scsi_status = scsi_req->scsi_status;
804		/* If simq is frozen, unfreeze it. */
805		if (sc->state & TW_OSLI_CTLR_STATE_SIMQ_FROZEN)
806			tw_osli_allow_new_requests(sc, (TW_VOID *)ccb);
807	}
808
809	ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
810	xpt_done(ccb);
811	if (! req->error_code)
812		 /* twa_action will free the request otherwise */
813		tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q);
814}
815
816