tw_osl_cam.c revision 246713
1209139Srpaulo/*
2209139Srpaulo * Copyright (c) 2004-07 Applied Micro Circuits Corporation.
3209139Srpaulo * Copyright (c) 2004-05 Vinod Kashyap.
4209139Srpaulo * All rights reserved.
5252726Srpaulo *
6252726Srpaulo * Redistribution and use in source and binary forms, with or without
7209139Srpaulo * modification, are permitted provided that the following conditions
8209139Srpaulo * are met:
9209139Srpaulo * 1. Redistributions of source code must retain the above copyright
10209139Srpaulo *    notice, this list of conditions and the following disclaimer.
11209139Srpaulo * 2. Redistributions in binary form must reproduce the above copyright
12209139Srpaulo *    notice, this list of conditions and the following disclaimer in the
13209139Srpaulo *    documentation and/or other materials provided with the distribution.
14209139Srpaulo *
15209139Srpaulo * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16209139Srpaulo * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17209139Srpaulo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18209139Srpaulo * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19209139Srpaulo * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20209139Srpaulo * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21209139Srpaulo * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22209139Srpaulo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23209139Srpaulo * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24209139Srpaulo * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25209139Srpaulo * SUCH DAMAGE.
26209139Srpaulo *
27209139Srpaulo *	$FreeBSD: head/sys/dev/twa/tw_osl_cam.c 246713 2013-02-12 16:57:20Z kib $
28209139Srpaulo */
29209139Srpaulo
30209139Srpaulo/*
31209139Srpaulo * AMCC'S 3ware driver for 9000 series storage controllers.
32209139Srpaulo *
33209139Srpaulo * Author: Vinod Kashyap
34209139Srpaulo * Modifications by: Adam Radford
35252726Srpaulo * Modifications by: Manjunath Ranganathaiah
36252726Srpaulo */
37252726Srpaulo
38252726Srpaulo
39209139Srpaulo/*
40252726Srpaulo * FreeBSD CAM related functions.
41209139Srpaulo */
42209139Srpaulo
43209139Srpaulo
44209139Srpaulo#include <dev/twa/tw_osl_includes.h>
45209139Srpaulo
46209139Srpaulo#include <cam/cam.h>
47209139Srpaulo#include <cam/cam_ccb.h>
48209139Srpaulo#include <cam/cam_sim.h>
49209139Srpaulo#include <cam/cam_xpt_sim.h>
50209139Srpaulo#include <cam/cam_debug.h>
51209139Srpaulo#include <cam/cam_periph.h>
52209139Srpaulo
53209139Srpaulo#include <cam/scsi/scsi_all.h>
54209139Srpaulo#include <cam/scsi/scsi_message.h>
55209139Srpaulo
56209139Srpaulostatic TW_VOID	twa_action(struct cam_sim *sim, union ccb *ccb);
57209139Srpaulostatic TW_VOID	twa_poll(struct cam_sim *sim);
58209139Srpaulo
59209139Srpaulostatic TW_INT32	tw_osli_execute_scsi(struct tw_osli_req_context *req,
60209139Srpaulo	union ccb *ccb);
61209139Srpaulo
62209139Srpaulo
63209139Srpaulo
64209139Srpaulo/*
65209139Srpaulo * Function name:	tw_osli_cam_attach
66209139Srpaulo * Description:		Attaches the driver to CAM.
67209139Srpaulo *
68209139Srpaulo * Input:		sc	-- ptr to OSL internal ctlr context
69209139Srpaulo * Output:		None
70209139Srpaulo * Return value:	0	-- success
71209139Srpaulo *			non-zero-- failure
72209139Srpaulo */
73209139SrpauloTW_INT32
74209139Srpaulotw_osli_cam_attach(struct twa_softc *sc)
75209139Srpaulo{
76209139Srpaulo	struct cam_devq		*devq;
77209139Srpaulo
78209139Srpaulo	tw_osli_dbg_dprintf(3, sc, "entered");
79209139Srpaulo
80209139Srpaulo	/*
81209139Srpaulo	 * Create the device queue for our SIM.
82209139Srpaulo	 */
83209139Srpaulo	if ((devq = cam_simq_alloc(TW_OSLI_MAX_NUM_IOS)) == NULL) {
84209139Srpaulo		tw_osli_printf(sc, "error = %d",
85209139Srpaulo			TW_CL_SEVERITY_ERROR_STRING,
86209139Srpaulo			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
87209139Srpaulo			0x2100,
88209139Srpaulo			"Failed to create SIM device queue",
89209139Srpaulo			ENOMEM);
90209139Srpaulo		return(ENOMEM);
91209139Srpaulo	}
92209139Srpaulo
93209139Srpaulo	/*
94209139Srpaulo	 * Create a SIM entry.  Though we can support TW_OSLI_MAX_NUM_REQUESTS
95209139Srpaulo	 * simultaneous requests, we claim to be able to handle only
96209139Srpaulo	 * TW_OSLI_MAX_NUM_IOS (two less), so that we always have a request
97209139Srpaulo	 * packet available to service ioctls and AENs.
98209139Srpaulo	 */
99209139Srpaulo	tw_osli_dbg_dprintf(3, sc, "Calling cam_sim_alloc");
100209139Srpaulo	sc->sim = cam_sim_alloc(twa_action, twa_poll, "twa", sc,
101209139Srpaulo			device_get_unit(sc->bus_dev), sc->sim_lock,
102209139Srpaulo			TW_OSLI_MAX_NUM_IOS, 1, devq);
103209139Srpaulo	if (sc->sim == NULL) {
104209139Srpaulo		cam_simq_free(devq);
105209139Srpaulo		tw_osli_printf(sc, "error = %d",
106209139Srpaulo			TW_CL_SEVERITY_ERROR_STRING,
107209139Srpaulo			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
108209139Srpaulo			0x2101,
109209139Srpaulo			"Failed to create a SIM entry",
110209139Srpaulo			ENOMEM);
111209139Srpaulo		return(ENOMEM);
112209139Srpaulo	}
113209139Srpaulo
114209139Srpaulo	/*
115209139Srpaulo	 * Register the bus.
116209139Srpaulo	 */
117209139Srpaulo	tw_osli_dbg_dprintf(3, sc, "Calling xpt_bus_register");
118209139Srpaulo	mtx_lock(sc->sim_lock);
119209139Srpaulo	if (xpt_bus_register(sc->sim, sc->bus_dev, 0) != CAM_SUCCESS) {
120209139Srpaulo		cam_sim_free(sc->sim, TRUE);
121209139Srpaulo		sc->sim = NULL; /* so cam_detach will not try to free it */
122209139Srpaulo		tw_osli_printf(sc, "error = %d",
123209139Srpaulo			TW_CL_SEVERITY_ERROR_STRING,
124209139Srpaulo			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
125209139Srpaulo			0x2102,
126209139Srpaulo			"Failed to register the bus",
127209139Srpaulo			ENXIO);
128209139Srpaulo		mtx_unlock(sc->sim_lock);
129209139Srpaulo		return(ENXIO);
130209139Srpaulo	}
131209139Srpaulo
132209139Srpaulo	tw_osli_dbg_dprintf(3, sc, "Calling xpt_create_path");
133209139Srpaulo	if (xpt_create_path(&sc->path, NULL,
134209139Srpaulo				cam_sim_path(sc->sim),
135209139Srpaulo				CAM_TARGET_WILDCARD,
136209139Srpaulo				CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
137209139Srpaulo		xpt_bus_deregister(cam_sim_path (sc->sim));
138209139Srpaulo		/* Passing TRUE to cam_sim_free will free the devq as well. */
139209139Srpaulo		cam_sim_free(sc->sim, TRUE);
140209139Srpaulo		tw_osli_printf(sc, "error = %d",
141209139Srpaulo			TW_CL_SEVERITY_ERROR_STRING,
142209139Srpaulo			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
143209139Srpaulo			0x2103,
144209139Srpaulo			"Failed to create path",
145209139Srpaulo			ENXIO);
146209139Srpaulo		mtx_unlock(sc->sim_lock);
147209139Srpaulo		return(ENXIO);
148209139Srpaulo	}
149209139Srpaulo	mtx_unlock(sc->sim_lock);
150209139Srpaulo
151209139Srpaulo	tw_osli_dbg_dprintf(3, sc, "exiting");
152209139Srpaulo	return(0);
153209139Srpaulo}
154209139Srpaulo
155209139Srpaulo
156209139Srpaulo
157209139Srpaulo/*
158209139Srpaulo * Function name:	tw_osli_cam_detach
159209139Srpaulo * Description:		Detaches the driver from CAM.
160209139Srpaulo *
161209139Srpaulo * Input:		sc	-- ptr to OSL internal ctlr context
162209139Srpaulo * Output:		None
163209139Srpaulo * Return value:	None
164209139Srpaulo */
165209139SrpauloTW_VOID
166209139Srpaulotw_osli_cam_detach(struct twa_softc *sc)
167209139Srpaulo{
168209139Srpaulo	tw_osli_dbg_dprintf(3, sc, "entered");
169209139Srpaulo
170209139Srpaulo	mtx_lock(sc->sim_lock);
171209139Srpaulo
172209139Srpaulo	if (sc->path)
173209139Srpaulo		xpt_free_path(sc->path);
174209139Srpaulo	if (sc->sim) {
175209139Srpaulo		xpt_bus_deregister(cam_sim_path(sc->sim));
176209139Srpaulo		/* Passing TRUE to cam_sim_free will free the devq as well. */
177209139Srpaulo		cam_sim_free(sc->sim, TRUE);
178209139Srpaulo	}
179209139Srpaulo	/* It's ok have 1 hold count while destroying the mutex */
180209139Srpaulo	mtx_destroy(sc->sim_lock);
181209139Srpaulo}
182209139Srpaulo
183209139Srpaulo
184209139Srpaulo
185209139Srpaulo/*
186209139Srpaulo * Function name:	tw_osli_execute_scsi
187209139Srpaulo * Description:		Build a fw cmd, based on a CAM style ccb, and
188209139Srpaulo *			send it down.
189209139Srpaulo *
190209139Srpaulo * Input:		req	-- ptr to OSL internal request context
191209139Srpaulo *			ccb	-- ptr to CAM style ccb
192209139Srpaulo * Output:		None
193209139Srpaulo * Return value:	0	-- success
194209139Srpaulo *			non-zero-- failure
195209139Srpaulo */
196209139SrpauloTW_INT32
197209139Srpaulotw_osli_execute_scsi(struct tw_osli_req_context *req, union ccb *ccb)
198209139Srpaulo{
199209139Srpaulo	struct twa_softc		*sc = req->ctlr;
200209139Srpaulo	struct tw_cl_req_packet		*req_pkt;
201209139Srpaulo	struct tw_cl_scsi_req_packet	*scsi_req;
202209139Srpaulo	struct ccb_hdr			*ccb_h = &(ccb->ccb_h);
203209139Srpaulo	struct ccb_scsiio		*csio = &(ccb->csio);
204209139Srpaulo	TW_INT32			error;
205209139Srpaulo
206209139Srpaulo	tw_osli_dbg_dprintf(10, sc, "SCSI I/O request 0x%x",
207209139Srpaulo		csio->cdb_io.cdb_bytes[0]);
208209139Srpaulo
209209139Srpaulo	if (ccb_h->target_id >= TW_CL_MAX_NUM_UNITS) {
210209139Srpaulo		tw_osli_dbg_dprintf(3, sc, "Invalid target. PTL = %x %x %x",
211209139Srpaulo			ccb_h->path_id, ccb_h->target_id, ccb_h->target_lun);
212209139Srpaulo		ccb_h->status |= CAM_TID_INVALID;
213209139Srpaulo		xpt_done(ccb);
214209139Srpaulo		return(1);
215209139Srpaulo	}
216209139Srpaulo	if (ccb_h->target_lun >= TW_CL_MAX_NUM_LUNS) {
217209139Srpaulo		tw_osli_dbg_dprintf(3, sc, "Invalid lun. PTL = %x %x %x",
218209139Srpaulo			ccb_h->path_id, ccb_h->target_id, ccb_h->target_lun);
219209139Srpaulo		ccb_h->status |= CAM_LUN_INVALID;
220209139Srpaulo		xpt_done(ccb);
221209139Srpaulo		return(1);
222209139Srpaulo	}
223209139Srpaulo
224209139Srpaulo	if(ccb_h->flags & CAM_CDB_PHYS) {
225209139Srpaulo		tw_osli_printf(sc, "",
226			TW_CL_SEVERITY_ERROR_STRING,
227			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
228			0x2105,
229			"Physical CDB address!");
230		ccb_h->status = CAM_REQ_INVALID;
231		xpt_done(ccb);
232		return(1);
233	}
234
235	/*
236	 * We are going to work on this request.  Mark it as enqueued (though
237	 * we don't actually queue it...)
238	 */
239	ccb_h->status |= CAM_SIM_QUEUED;
240
241	if((ccb_h->flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
242		if(ccb_h->flags & CAM_DIR_IN)
243			req->flags |= TW_OSLI_REQ_FLAGS_DATA_IN;
244		else
245			req->flags |= TW_OSLI_REQ_FLAGS_DATA_OUT;
246	}
247
248	/* Build the CL understood request packet for SCSI cmds. */
249	req_pkt = &req->req_pkt;
250	req_pkt->status = 0;
251	req_pkt->tw_osl_callback = tw_osl_complete_io;
252	scsi_req = &(req_pkt->gen_req_pkt.scsi_req);
253	scsi_req->unit = ccb_h->target_id;
254	scsi_req->lun = ccb_h->target_lun;
255	scsi_req->sense_len = 0;
256	scsi_req->sense_data = (TW_UINT8 *)(&csio->sense_data);
257	scsi_req->scsi_status = 0;
258	if(ccb_h->flags & CAM_CDB_POINTER)
259		scsi_req->cdb = csio->cdb_io.cdb_ptr;
260	else
261		scsi_req->cdb = csio->cdb_io.cdb_bytes;
262	scsi_req->cdb_len = csio->cdb_len;
263
264	if (csio->dxfer_len > TW_CL_MAX_IO_SIZE) {
265		tw_osli_printf(sc, "size = %d",
266			TW_CL_SEVERITY_ERROR_STRING,
267			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
268			0x2106,
269			"I/O size too big",
270			csio->dxfer_len);
271		ccb_h->status = CAM_REQ_TOO_BIG;
272		ccb_h->status &= ~CAM_SIM_QUEUED;
273		xpt_done(ccb);
274		return(1);
275	}
276	req->data = ccb;
277	req->length = csio->dxfer_len;
278	req->flags |= TW_OSLI_REQ_FLAGS_CCB;
279	req->deadline = tw_osl_get_local_time() + (ccb_h->timeout / 1000);
280
281	/*
282	 * twa_map_load_data_callback will fill in the SGL,
283	 * and submit the I/O.
284	 */
285	error = tw_osli_map_request(req);
286	if ((error) && (req->flags & TW_OSLI_REQ_FLAGS_FAILED)) {
287		req->deadline = 0;
288		ccb_h->status = CAM_REQ_CMP_ERR;
289		ccb_h->status &= ~CAM_SIM_QUEUED;
290		xpt_done(ccb);
291	}
292	return(error);
293}
294
295
296
297/*
298 * Function name:	twa_action
299 * Description:		Driver entry point for CAM's use.
300 *
301 * Input:		sim	-- sim corresponding to the ctlr
302 *			ccb	-- ptr to CAM request
303 * Output:		None
304 * Return value:	None
305 */
306TW_VOID
307twa_action(struct cam_sim *sim, union ccb *ccb)
308{
309	struct twa_softc	*sc = (struct twa_softc *)cam_sim_softc(sim);
310	struct ccb_hdr		*ccb_h = &(ccb->ccb_h);
311
312	switch (ccb_h->func_code) {
313	case XPT_SCSI_IO:	/* SCSI I/O */
314	{
315		struct tw_osli_req_context	*req;
316
317		req = tw_osli_get_request(sc);
318		if (req == NULL) {
319			tw_osli_dbg_dprintf(2, sc, "Cannot get request pkt.");
320			/*
321			 * Freeze the simq to maintain ccb ordering.  The next
322			 * ccb that gets completed will unfreeze the simq.
323			 */
324			ccb_h->status &= ~CAM_SIM_QUEUED;
325			ccb_h->status |= CAM_REQUEUE_REQ;
326			xpt_done(ccb);
327			break;
328		}
329
330		if ((tw_cl_is_reset_needed(&(req->ctlr->ctlr_handle)))) {
331			ccb_h->status &= ~CAM_SIM_QUEUED;
332			ccb_h->status |= CAM_REQUEUE_REQ;
333			xpt_done(ccb);
334			tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q);
335			break;
336		}
337
338		req->req_handle.osl_req_ctxt = req;
339		req->req_handle.is_io = TW_CL_TRUE;
340		req->orig_req = ccb;
341		if (tw_osli_execute_scsi(req, ccb))
342			tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q);
343		break;
344	}
345
346	case XPT_ABORT:
347		tw_osli_dbg_dprintf(2, sc, "Abort request.");
348		ccb_h->status = CAM_UA_ABORT;
349		xpt_done(ccb);
350		break;
351
352	case XPT_RESET_BUS:
353		tw_cl_create_event(&(sc->ctlr_handle), TW_CL_FALSE,
354			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
355			0x2108, 0x3, TW_CL_SEVERITY_INFO_STRING,
356			"Received Reset Bus request from CAM",
357			" ");
358
359		tw_cl_set_reset_needed(&(sc->ctlr_handle));
360		ccb_h->status = CAM_REQ_CMP;
361		xpt_done(ccb);
362		break;
363
364	case XPT_SET_TRAN_SETTINGS:
365		tw_osli_dbg_dprintf(3, sc, "XPT_SET_TRAN_SETTINGS");
366
367		/*
368		 * This command is not supported, since it's very specific
369		 * to SCSI, and we are doing ATA.
370		 */
371  		ccb_h->status = CAM_FUNC_NOTAVAIL;
372  		xpt_done(ccb);
373  		break;
374
375	case XPT_GET_TRAN_SETTINGS:
376	{
377		struct ccb_trans_settings	*cts = &ccb->cts;
378		struct ccb_trans_settings_scsi *scsi =
379		    &cts->proto_specific.scsi;
380		struct ccb_trans_settings_spi *spi =
381		    &cts->xport_specific.spi;
382
383		cts->protocol = PROTO_SCSI;
384		cts->protocol_version = SCSI_REV_2;
385		cts->transport = XPORT_SPI;
386		cts->transport_version = 2;
387
388		spi->valid = CTS_SPI_VALID_DISC;
389		spi->flags = CTS_SPI_FLAGS_DISC_ENB;
390		scsi->valid = CTS_SCSI_VALID_TQ;
391		scsi->flags = CTS_SCSI_FLAGS_TAG_ENB;
392		tw_osli_dbg_dprintf(3, sc, "XPT_GET_TRAN_SETTINGS");
393		ccb_h->status = CAM_REQ_CMP;
394		xpt_done(ccb);
395		break;
396	}
397
398	case XPT_CALC_GEOMETRY:
399		tw_osli_dbg_dprintf(3, sc, "XPT_CALC_GEOMETRY");
400		cam_calc_geometry(&ccb->ccg, 1/* extended */);
401		xpt_done(ccb);
402		break;
403
404	case XPT_PATH_INQ:    /* Path inquiry -- get twa properties */
405	{
406		struct ccb_pathinq	*path_inq = &ccb->cpi;
407
408		tw_osli_dbg_dprintf(3, sc, "XPT_PATH_INQ request");
409
410		path_inq->version_num = 1;
411		path_inq->hba_inquiry = 0;
412		path_inq->target_sprt = 0;
413		path_inq->hba_misc = 0;
414		path_inq->hba_eng_cnt = 0;
415		path_inq->max_target = TW_CL_MAX_NUM_UNITS;
416		path_inq->max_lun = TW_CL_MAX_NUM_LUNS - 1;
417		path_inq->unit_number = cam_sim_unit(sim);
418		path_inq->bus_id = cam_sim_bus(sim);
419		path_inq->initiator_id = TW_CL_MAX_NUM_UNITS;
420		path_inq->base_transfer_speed = 100000;
421		strncpy(path_inq->sim_vid, "FreeBSD", SIM_IDLEN);
422		strncpy(path_inq->hba_vid, "3ware", HBA_IDLEN);
423		strncpy(path_inq->dev_name, cam_sim_name(sim), DEV_IDLEN);
424                path_inq->transport = XPORT_SPI;
425                path_inq->transport_version = 2;
426                path_inq->protocol = PROTO_SCSI;
427                path_inq->protocol_version = SCSI_REV_2;
428                path_inq->maxio = TW_CL_MAX_IO_SIZE;
429		ccb_h->status = CAM_REQ_CMP;
430		xpt_done(ccb);
431		break;
432	}
433
434	default:
435		tw_osli_dbg_dprintf(3, sc, "func_code = %x", ccb_h->func_code);
436		ccb_h->status = CAM_REQ_INVALID;
437		xpt_done(ccb);
438		break;
439	}
440}
441
442
443
444/*
445 * Function name:	twa_poll
446 * Description:		Driver entry point called when interrupts are not
447 *			available.
448 *
449 * Input:		sim	-- sim corresponding to the controller
450 * Output:		None
451 * Return value:	None
452 */
453TW_VOID
454twa_poll(struct cam_sim *sim)
455{
456	struct twa_softc *sc = (struct twa_softc *)(cam_sim_softc(sim));
457
458	tw_osli_dbg_dprintf(3, sc, "entering; sc = %p", sc);
459	tw_cl_interrupt(&(sc->ctlr_handle));
460	tw_osli_dbg_dprintf(3, sc, "exiting; sc = %p", sc);
461}
462
463
464
465/*
466 * Function name:	tw_osli_request_bus_scan
467 * Description:		Requests CAM for a scan of the bus.
468 *
469 * Input:		sc	-- ptr to per ctlr structure
470 * Output:		None
471 * Return value:	0	-- success
472 *			non-zero-- failure
473 */
474TW_INT32
475tw_osli_request_bus_scan(struct twa_softc *sc)
476{
477	union ccb	*ccb;
478
479	tw_osli_dbg_dprintf(3, sc, "entering");
480
481	/* If we get here before sc->sim is initialized, return an error. */
482	if (!(sc->sim))
483		return(ENXIO);
484	if ((ccb = xpt_alloc_ccb()) == NULL)
485		return(ENOMEM);
486	mtx_lock(sc->sim_lock);
487	if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, cam_sim_path(sc->sim),
488	    CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
489		xpt_free_ccb(ccb);
490		mtx_unlock(sc->sim_lock);
491		return(EIO);
492	}
493
494	xpt_rescan(ccb);
495	mtx_unlock(sc->sim_lock);
496	return(0);
497}
498
499
500
501/*
502 * Function name:	tw_osli_disallow_new_requests
503 * Description:		Calls the appropriate CAM function, so as to freeze
504 *			the flow of new requests from CAM to this controller.
505 *
506 * Input:		sc	-- ptr to OSL internal ctlr context
507 *			req_handle -- ptr to request handle sent by OSL.
508 * Output:		None
509 * Return value:	None
510 */
511TW_VOID
512tw_osli_disallow_new_requests(struct twa_softc *sc,
513	struct tw_cl_req_handle *req_handle)
514{
515	/* Only freeze/release the simq for IOs */
516	if (req_handle->is_io) {
517		struct tw_osli_req_context	*req = req_handle->osl_req_ctxt;
518		union ccb			*ccb = (union ccb *)(req->orig_req);
519
520		xpt_freeze_simq(sc->sim, 1);
521		ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
522	}
523}
524
525
526
527/*
528 * Function name:	tw_osl_timeout
529 * Description:		Call to timeout().
530 *
531 * Input:		req_handle -- ptr to request handle sent by OSL.
532 * Output:		None
533 * Return value:	None
534 */
535TW_VOID
536tw_osl_timeout(struct tw_cl_req_handle *req_handle)
537{
538	struct tw_osli_req_context	*req = req_handle->osl_req_ctxt;
539	union ccb			*ccb = (union ccb *)(req->orig_req);
540	struct ccb_hdr			*ccb_h = &(ccb->ccb_h);
541
542	req->deadline = tw_osl_get_local_time() + (ccb_h->timeout / 1000);
543}
544
545
546
547/*
548 * Function name:	tw_osl_untimeout
549 * Description:		Inverse of call to timeout().
550 *
551 * Input:		req_handle -- ptr to request handle sent by OSL.
552 * Output:		None
553 * Return value:	None
554 */
555TW_VOID
556tw_osl_untimeout(struct tw_cl_req_handle *req_handle)
557{
558	struct tw_osli_req_context	*req = req_handle->osl_req_ctxt;
559
560	req->deadline = 0;
561}
562
563
564
565/*
566 * Function name:	tw_osl_scan_bus
567 * Description:		CL calls this function to request for a bus scan.
568 *
569 * Input:		ctlr_handle	-- ptr to controller handle
570 * Output:		None
571 * Return value:	None
572 */
573TW_VOID
574tw_osl_scan_bus(struct tw_cl_ctlr_handle *ctlr_handle)
575{
576	struct twa_softc	*sc = ctlr_handle->osl_ctlr_ctxt;
577	TW_INT32		error;
578
579	if ((error = tw_osli_request_bus_scan(sc)))
580		tw_osli_printf(sc, "error = %d",
581			TW_CL_SEVERITY_ERROR_STRING,
582			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
583			0x2109,
584			"Bus scan request to CAM failed",
585			error);
586}
587
588
589
590/*
591 * Function name:	tw_osl_complete_io
592 * Description:		Called to complete CAM scsi requests.
593 *
594 * Input:		req_handle	-- ptr to request handle
595 * Output:		None
596 * Return value:	None
597 */
598TW_VOID
599tw_osl_complete_io(struct tw_cl_req_handle *req_handle)
600{
601	struct tw_osli_req_context	*req = req_handle->osl_req_ctxt;
602	struct tw_cl_req_packet		*req_pkt =
603		(struct tw_cl_req_packet *)(&req->req_pkt);
604	struct tw_cl_scsi_req_packet	*scsi_req;
605	struct twa_softc		*sc = req->ctlr;
606	union ccb			*ccb = (union ccb *)(req->orig_req);
607
608	tw_osli_dbg_dprintf(10, sc, "entering");
609
610	if (req->state != TW_OSLI_REQ_STATE_BUSY)
611		tw_osli_printf(sc, "request = %p, status = %d",
612			TW_CL_SEVERITY_ERROR_STRING,
613			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
614			0x210A,
615			"Unposted command completed!!",
616			req, req->state);
617
618	/*
619	 * Remove request from the busy queue.  Just mark it complete.
620	 * There's no need to move it into the complete queue as we are
621	 * going to be done with it right now.
622	 */
623	req->state = TW_OSLI_REQ_STATE_COMPLETE;
624	tw_osli_req_q_remove_item(req, TW_OSLI_BUSY_Q);
625
626	tw_osli_unmap_request(req);
627
628	req->deadline = 0;
629	if (req->error_code) {
630		/* This request never got submitted to the firmware. */
631		if (req->error_code == EBUSY) {
632			/*
633			 * Cmd queue is full, or the Common Layer is out of
634			 * resources.  The simq will already have been frozen.
635			 * When this ccb gets completed will unfreeze the simq.
636			 */
637			ccb->ccb_h.status |= CAM_REQUEUE_REQ;
638		}
639		else if (req->error_code == EFBIG)
640			ccb->ccb_h.status = CAM_REQ_TOO_BIG;
641		else
642			ccb->ccb_h.status = CAM_REQ_CMP_ERR;
643	} else {
644		scsi_req = &(req_pkt->gen_req_pkt.scsi_req);
645		if (req_pkt->status == TW_CL_ERR_REQ_SUCCESS)
646			ccb->ccb_h.status = CAM_REQ_CMP;
647		else {
648			if (req_pkt->status & TW_CL_ERR_REQ_INVALID_TARGET)
649				ccb->ccb_h.status |= CAM_SEL_TIMEOUT;
650			else if (req_pkt->status & TW_CL_ERR_REQ_INVALID_LUN)
651				ccb->ccb_h.status |= CAM_DEV_NOT_THERE;
652			else if (req_pkt->status & TW_CL_ERR_REQ_SCSI_ERROR)
653				ccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
654			else if (req_pkt->status & TW_CL_ERR_REQ_BUS_RESET)
655				ccb->ccb_h.status |= (CAM_REQUEUE_REQ | CAM_SCSI_BUS_RESET);
656			/*
657			 * If none of the above errors occurred, simply
658			 * mark completion error.
659			 */
660			if (ccb->ccb_h.status == 0)
661				ccb->ccb_h.status = CAM_REQ_CMP_ERR;
662
663			if (req_pkt->status & TW_CL_ERR_REQ_AUTO_SENSE_VALID) {
664				ccb->csio.sense_len = scsi_req->sense_len;
665				ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
666			}
667		}
668
669		ccb->csio.scsi_status = scsi_req->scsi_status;
670	}
671
672	ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
673	mtx_lock(sc->sim_lock);
674	xpt_done(ccb);
675	mtx_unlock(sc->sim_lock);
676	if (! req->error_code)
677		 /* twa_action will free the request otherwise */
678		tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q);
679}
680
681