tw_osl_cam.c revision 208969
1144966Svkashyap/*
2169400Sscottl * Copyright (c) 2004-07 Applied Micro Circuits Corporation.
3144966Svkashyap * Copyright (c) 2004-05 Vinod Kashyap.
4144966Svkashyap * All rights reserved.
5144966Svkashyap *
6144966Svkashyap * Redistribution and use in source and binary forms, with or without
7144966Svkashyap * modification, are permitted provided that the following conditions
8144966Svkashyap * are met:
9144966Svkashyap * 1. Redistributions of source code must retain the above copyright
10144966Svkashyap *    notice, this list of conditions and the following disclaimer.
11144966Svkashyap * 2. Redistributions in binary form must reproduce the above copyright
12144966Svkashyap *    notice, this list of conditions and the following disclaimer in the
13144966Svkashyap *    documentation and/or other materials provided with the distribution.
14144966Svkashyap *
15144966Svkashyap * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16144966Svkashyap * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17144966Svkashyap * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18144966Svkashyap * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19144966Svkashyap * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20144966Svkashyap * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21144966Svkashyap * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22144966Svkashyap * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23144966Svkashyap * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24144966Svkashyap * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25144966Svkashyap * SUCH DAMAGE.
26144966Svkashyap *
27144966Svkashyap *	$FreeBSD: head/sys/dev/twa/tw_osl_cam.c 208969 2010-06-09 21:40:38Z delphij $
28144966Svkashyap */
29144966Svkashyap
30144966Svkashyap/*
31144966Svkashyap * AMCC'S 3ware driver for 9000 series storage controllers.
32144966Svkashyap *
33144966Svkashyap * Author: Vinod Kashyap
34169400Sscottl * Modifications by: Adam Radford
35172496Sscottl * Modifications by: Manjunath Ranganathaiah
36144966Svkashyap */
37144966Svkashyap
38144966Svkashyap
39144966Svkashyap/*
40144966Svkashyap * FreeBSD CAM related functions.
41144966Svkashyap */
42144966Svkashyap
43144966Svkashyap
44149968Sobrien#include <dev/twa/tw_osl_includes.h>
45144966Svkashyap
46144966Svkashyap#include <cam/cam.h>
47144966Svkashyap#include <cam/cam_ccb.h>
48144966Svkashyap#include <cam/cam_sim.h>
49144966Svkashyap#include <cam/cam_xpt_sim.h>
50144966Svkashyap#include <cam/cam_debug.h>
51144966Svkashyap#include <cam/cam_periph.h>
52144966Svkashyap
53144966Svkashyap#include <cam/scsi/scsi_all.h>
54144966Svkashyap#include <cam/scsi/scsi_message.h>
55144966Svkashyap
56144966Svkashyapstatic TW_VOID	twa_action(struct cam_sim *sim, union ccb *ccb);
57144966Svkashyapstatic TW_VOID	twa_poll(struct cam_sim *sim);
58144966Svkashyapstatic TW_VOID	twa_timeout(TW_VOID *arg);
59144966Svkashyap
60144966Svkashyapstatic TW_INT32	tw_osli_execute_scsi(struct tw_osli_req_context *req,
61144966Svkashyap	union ccb *ccb);
62144966Svkashyap
63144966Svkashyap
64144966Svkashyap
65144966Svkashyap/*
66144966Svkashyap * Function name:	tw_osli_cam_attach
67144966Svkashyap * Description:		Attaches the driver to CAM.
68144966Svkashyap *
69144966Svkashyap * Input:		sc	-- ptr to OSL internal ctlr context
70144966Svkashyap * Output:		None
71144966Svkashyap * Return value:	0	-- success
72144966Svkashyap *			non-zero-- failure
73144966Svkashyap */
74144966SvkashyapTW_INT32
75144966Svkashyaptw_osli_cam_attach(struct twa_softc *sc)
76144966Svkashyap{
77144966Svkashyap	struct cam_devq		*devq;
78144966Svkashyap
79144966Svkashyap	tw_osli_dbg_dprintf(3, sc, "entered");
80144966Svkashyap
81144966Svkashyap	/*
82144966Svkashyap	 * Create the device queue for our SIM.
83144966Svkashyap	 */
84208969Sdelphij	if ((devq = cam_simq_alloc(TW_OSLI_MAX_NUM_REQUESTS)) == NULL) {
85144966Svkashyap		tw_osli_printf(sc, "error = %d",
86144966Svkashyap			TW_CL_SEVERITY_ERROR_STRING,
87144966Svkashyap			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
88144966Svkashyap			0x2100,
89144966Svkashyap			"Failed to create SIM device queue",
90144966Svkashyap			ENOMEM);
91144966Svkashyap		return(ENOMEM);
92144966Svkashyap	}
93144966Svkashyap
94144966Svkashyap	/*
95208969Sdelphij	 * Create a SIM entry.  Though we can support TW_OSLI_MAX_NUM_REQUESTS
96144966Svkashyap	 * simultaneous requests, we claim to be able to handle only
97208969Sdelphij	 * TW_OSLI_MAX_NUM_IOS (two less), so that we always have a request
98208969Sdelphij	 * packet available to service ioctls and AENs.
99144966Svkashyap	 */
100144966Svkashyap	tw_osli_dbg_dprintf(3, sc, "Calling cam_sim_alloc");
101144966Svkashyap	sc->sim = cam_sim_alloc(twa_action, twa_poll, "twa", sc,
102172496Sscottl			device_get_unit(sc->bus_dev), sc->sim_lock,
103208969Sdelphij			TW_OSLI_MAX_NUM_IOS, 1, devq);
104144966Svkashyap	if (sc->sim == NULL) {
105144966Svkashyap		cam_simq_free(devq);
106144966Svkashyap		tw_osli_printf(sc, "error = %d",
107144966Svkashyap			TW_CL_SEVERITY_ERROR_STRING,
108144966Svkashyap			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
109144966Svkashyap			0x2101,
110144966Svkashyap			"Failed to create a SIM entry",
111144966Svkashyap			ENOMEM);
112144966Svkashyap		return(ENOMEM);
113144966Svkashyap	}
114144966Svkashyap
115144966Svkashyap	/*
116144966Svkashyap	 * Register the bus.
117144966Svkashyap	 */
118144966Svkashyap	tw_osli_dbg_dprintf(3, sc, "Calling xpt_bus_register");
119172496Sscottl	mtx_lock(sc->sim_lock);
120170872Sscottl	if (xpt_bus_register(sc->sim, sc->bus_dev, 0) != CAM_SUCCESS) {
121144966Svkashyap		cam_sim_free(sc->sim, TRUE);
122144966Svkashyap		sc->sim = NULL; /* so cam_detach will not try to free it */
123144966Svkashyap		tw_osli_printf(sc, "error = %d",
124144966Svkashyap			TW_CL_SEVERITY_ERROR_STRING,
125144966Svkashyap			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
126144966Svkashyap			0x2102,
127144966Svkashyap			"Failed to register the bus",
128144966Svkashyap			ENXIO);
129172496Sscottl		mtx_unlock(sc->sim_lock);
130144966Svkashyap		return(ENXIO);
131144966Svkashyap	}
132144966Svkashyap
133144966Svkashyap	tw_osli_dbg_dprintf(3, sc, "Calling xpt_create_path");
134144966Svkashyap	if (xpt_create_path(&sc->path, NULL,
135144966Svkashyap				cam_sim_path(sc->sim),
136144966Svkashyap				CAM_TARGET_WILDCARD,
137144966Svkashyap				CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
138144966Svkashyap		xpt_bus_deregister(cam_sim_path (sc->sim));
139144966Svkashyap		/* Passing TRUE to cam_sim_free will free the devq as well. */
140144966Svkashyap		cam_sim_free(sc->sim, TRUE);
141144966Svkashyap		tw_osli_printf(sc, "error = %d",
142144966Svkashyap			TW_CL_SEVERITY_ERROR_STRING,
143144966Svkashyap			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
144144966Svkashyap			0x2103,
145144966Svkashyap			"Failed to create path",
146144966Svkashyap			ENXIO);
147172496Sscottl		mtx_unlock(sc->sim_lock);
148144966Svkashyap		return(ENXIO);
149144966Svkashyap	}
150172496Sscottl	mtx_unlock(sc->sim_lock);
151144966Svkashyap
152144966Svkashyap	tw_osli_dbg_dprintf(3, sc, "exiting");
153144966Svkashyap	return(0);
154144966Svkashyap}
155144966Svkashyap
156144966Svkashyap
157144966Svkashyap
158144966Svkashyap/*
159144966Svkashyap * Function name:	tw_osli_cam_detach
160144966Svkashyap * Description:		Detaches the driver from CAM.
161144966Svkashyap *
162144966Svkashyap * Input:		sc	-- ptr to OSL internal ctlr context
163144966Svkashyap * Output:		None
164144966Svkashyap * Return value:	None
165144966Svkashyap */
166144966SvkashyapTW_VOID
167144966Svkashyaptw_osli_cam_detach(struct twa_softc *sc)
168144966Svkashyap{
169144966Svkashyap	tw_osli_dbg_dprintf(3, sc, "entered");
170144966Svkashyap
171172496Sscottl	mtx_lock(sc->sim_lock);
172172496Sscottl
173144966Svkashyap	if (sc->path)
174144966Svkashyap		xpt_free_path(sc->path);
175144966Svkashyap	if (sc->sim) {
176144966Svkashyap		xpt_bus_deregister(cam_sim_path(sc->sim));
177144966Svkashyap		/* Passing TRUE to cam_sim_free will free the devq as well. */
178144966Svkashyap		cam_sim_free(sc->sim, TRUE);
179144966Svkashyap	}
180172496Sscottl	/* It's ok have 1 hold count while destroying the mutex */
181172496Sscottl	mtx_destroy(sc->sim_lock);
182144966Svkashyap}
183144966Svkashyap
184144966Svkashyap
185144966Svkashyap
186144966Svkashyap/*
187144966Svkashyap * Function name:	tw_osli_execute_scsi
188144966Svkashyap * Description:		Build a fw cmd, based on a CAM style ccb, and
189144966Svkashyap *			send it down.
190144966Svkashyap *
191144966Svkashyap * Input:		req	-- ptr to OSL internal request context
192144966Svkashyap *			ccb	-- ptr to CAM style ccb
193144966Svkashyap * Output:		None
194144966Svkashyap * Return value:	0	-- success
195144966Svkashyap *			non-zero-- failure
196144966Svkashyap */
197144966SvkashyapTW_INT32
198144966Svkashyaptw_osli_execute_scsi(struct tw_osli_req_context *req, union ccb *ccb)
199144966Svkashyap{
200144966Svkashyap	struct twa_softc		*sc = req->ctlr;
201144966Svkashyap	struct tw_cl_req_packet		*req_pkt;
202144966Svkashyap	struct tw_cl_scsi_req_packet	*scsi_req;
203144966Svkashyap	struct ccb_hdr			*ccb_h = &(ccb->ccb_h);
204144966Svkashyap	struct ccb_scsiio		*csio = &(ccb->csio);
205144966Svkashyap	TW_INT32			error;
206144966Svkashyap
207144966Svkashyap	tw_osli_dbg_dprintf(10, sc, "SCSI I/O request 0x%x",
208144966Svkashyap		csio->cdb_io.cdb_bytes[0]);
209144966Svkashyap
210144966Svkashyap	if (ccb_h->target_id >= TW_CL_MAX_NUM_UNITS) {
211144966Svkashyap		tw_osli_dbg_dprintf(3, sc, "Invalid target. PTL = %x %x %x",
212144966Svkashyap			ccb_h->path_id, ccb_h->target_id, ccb_h->target_lun);
213144966Svkashyap		ccb_h->status |= CAM_TID_INVALID;
214144966Svkashyap		xpt_done(ccb);
215144966Svkashyap		return(1);
216144966Svkashyap	}
217144966Svkashyap	if (ccb_h->target_lun >= TW_CL_MAX_NUM_LUNS) {
218144966Svkashyap		tw_osli_dbg_dprintf(3, sc, "Invalid lun. PTL = %x %x %x",
219144966Svkashyap			ccb_h->path_id, ccb_h->target_id, ccb_h->target_lun);
220144966Svkashyap		ccb_h->status |= CAM_LUN_INVALID;
221144966Svkashyap		xpt_done(ccb);
222144966Svkashyap		return(1);
223144966Svkashyap	}
224144966Svkashyap
225144966Svkashyap	if(ccb_h->flags & CAM_CDB_PHYS) {
226144966Svkashyap		tw_osli_printf(sc, "",
227144966Svkashyap			TW_CL_SEVERITY_ERROR_STRING,
228144966Svkashyap			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
229144966Svkashyap			0x2105,
230144966Svkashyap			"Physical CDB address!");
231208969Sdelphij		ccb_h->status = CAM_REQ_INVALID;
232144966Svkashyap		xpt_done(ccb);
233144966Svkashyap		return(1);
234144966Svkashyap	}
235144966Svkashyap
236144966Svkashyap	/*
237144966Svkashyap	 * We are going to work on this request.  Mark it as enqueued (though
238144966Svkashyap	 * we don't actually queue it...)
239144966Svkashyap	 */
240144966Svkashyap	ccb_h->status |= CAM_SIM_QUEUED;
241144966Svkashyap
242144966Svkashyap	if((ccb_h->flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
243144966Svkashyap		if(ccb_h->flags & CAM_DIR_IN)
244144966Svkashyap			req->flags |= TW_OSLI_REQ_FLAGS_DATA_IN;
245144966Svkashyap		else
246144966Svkashyap			req->flags |= TW_OSLI_REQ_FLAGS_DATA_OUT;
247144966Svkashyap	}
248144966Svkashyap
249144966Svkashyap	/* Build the CL understood request packet for SCSI cmds. */
250144966Svkashyap	req_pkt = &req->req_pkt;
251144966Svkashyap	req_pkt->status = 0;
252144966Svkashyap	req_pkt->tw_osl_callback = tw_osl_complete_io;
253144966Svkashyap	scsi_req = &(req_pkt->gen_req_pkt.scsi_req);
254144966Svkashyap	scsi_req->unit = ccb_h->target_id;
255144966Svkashyap	scsi_req->lun = ccb_h->target_lun;
256144966Svkashyap	scsi_req->sense_len = 0;
257144966Svkashyap	scsi_req->sense_data = (TW_UINT8 *)(&csio->sense_data);
258144966Svkashyap	scsi_req->scsi_status = 0;
259144966Svkashyap	if(ccb_h->flags & CAM_CDB_POINTER)
260144966Svkashyap		scsi_req->cdb = csio->cdb_io.cdb_ptr;
261144966Svkashyap	else
262144966Svkashyap		scsi_req->cdb = csio->cdb_io.cdb_bytes;
263144966Svkashyap	scsi_req->cdb_len = csio->cdb_len;
264144966Svkashyap
265144966Svkashyap	if (!(ccb_h->flags & CAM_DATA_PHYS)) {
266144966Svkashyap		/* Virtual data addresses.  Need to convert them... */
267144966Svkashyap		tw_osli_dbg_dprintf(3, sc,
268144966Svkashyap			"XPT_SCSI_IO: Single virtual address!");
269144966Svkashyap		if (!(ccb_h->flags & CAM_SCATTER_VALID)) {
270144966Svkashyap			if (csio->dxfer_len > TW_CL_MAX_IO_SIZE) {
271144966Svkashyap				tw_osli_printf(sc, "size = %d",
272144966Svkashyap					TW_CL_SEVERITY_ERROR_STRING,
273144966Svkashyap					TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
274144966Svkashyap					0x2106,
275144966Svkashyap					"I/O size too big",
276144966Svkashyap					csio->dxfer_len);
277144966Svkashyap				ccb_h->status = CAM_REQ_TOO_BIG;
278144966Svkashyap				xpt_done(ccb);
279144966Svkashyap				return(1);
280144966Svkashyap			}
281144966Svkashyap
282144966Svkashyap			if ((req->length = csio->dxfer_len)) {
283144966Svkashyap				req->data = csio->data_ptr;
284144966Svkashyap				scsi_req->sgl_entries = 1;
285144966Svkashyap			}
286144966Svkashyap		} else {
287144966Svkashyap			tw_osli_printf(sc, "",
288144966Svkashyap				TW_CL_SEVERITY_ERROR_STRING,
289144966Svkashyap				TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
290144966Svkashyap				0x2107,
291144966Svkashyap				"XPT_SCSI_IO: Got SGList");
292208969Sdelphij			ccb_h->status = CAM_REQ_INVALID;
293144966Svkashyap			xpt_done(ccb);
294144966Svkashyap			return(1);
295144966Svkashyap		}
296144966Svkashyap	} else {
297144966Svkashyap		/* Data addresses are physical. */
298144966Svkashyap		tw_osli_printf(sc, "",
299144966Svkashyap			TW_CL_SEVERITY_ERROR_STRING,
300144966Svkashyap			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
301144966Svkashyap			0x2108,
302144966Svkashyap			"XPT_SCSI_IO: Physical data addresses");
303208969Sdelphij		ccb_h->status = CAM_REQ_INVALID;
304144966Svkashyap		ccb_h->status &= ~CAM_SIM_QUEUED;
305144966Svkashyap		xpt_done(ccb);
306144966Svkashyap		return(1);
307144966Svkashyap	}
308144966Svkashyap
309144966Svkashyap	ccb_h->timeout_ch = timeout(twa_timeout, req,
310144966Svkashyap		(ccb_h->timeout * hz) / 1000);
311144966Svkashyap	/*
312144966Svkashyap	 * twa_map_load_data_callback will fill in the SGL,
313144966Svkashyap	 * and submit the I/O.
314144966Svkashyap	 */
315144966Svkashyap	error = tw_osli_map_request(req);
316144966Svkashyap	return(error);
317144966Svkashyap}
318144966Svkashyap
319144966Svkashyap
320144966Svkashyap
321144966Svkashyap/*
322144966Svkashyap * Function name:	twa_action
323144966Svkashyap * Description:		Driver entry point for CAM's use.
324144966Svkashyap *
325144966Svkashyap * Input:		sim	-- sim corresponding to the ctlr
326144966Svkashyap *			ccb	-- ptr to CAM request
327144966Svkashyap * Output:		None
328144966Svkashyap * Return value:	None
329144966Svkashyap */
330144966SvkashyapTW_VOID
331144966Svkashyaptwa_action(struct cam_sim *sim, union ccb *ccb)
332144966Svkashyap{
333144966Svkashyap	struct twa_softc	*sc = (struct twa_softc *)cam_sim_softc(sim);
334144966Svkashyap	struct ccb_hdr		*ccb_h = &(ccb->ccb_h);
335144966Svkashyap
336144966Svkashyap	switch (ccb_h->func_code) {
337144966Svkashyap	case XPT_SCSI_IO:	/* SCSI I/O */
338144966Svkashyap	{
339144966Svkashyap		struct tw_osli_req_context	*req;
340144966Svkashyap
341208969Sdelphij		req = tw_osli_get_request(sc);
342208969Sdelphij		if (req == NULL) {
343208969Sdelphij			tw_osli_dbg_dprintf(2, sc, "Cannot get request pkt.");
344144966Svkashyap			/*
345144966Svkashyap			 * Freeze the simq to maintain ccb ordering.  The next
346144966Svkashyap			 * ccb that gets completed will unfreeze the simq.
347144966Svkashyap			 */
348144966Svkashyap			ccb_h->status |= CAM_REQUEUE_REQ;
349144966Svkashyap			xpt_done(ccb);
350144966Svkashyap			break;
351144966Svkashyap		}
352144966Svkashyap		req->req_handle.osl_req_ctxt = req;
353208969Sdelphij		req->req_handle.is_io = TW_CL_TRUE;
354144966Svkashyap		req->orig_req = ccb;
355144966Svkashyap		if (tw_osli_execute_scsi(req, ccb))
356144966Svkashyap			tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q);
357144966Svkashyap		break;
358144966Svkashyap	}
359144966Svkashyap
360144966Svkashyap	case XPT_ABORT:
361144966Svkashyap		tw_osli_dbg_dprintf(2, sc, "Abort request.");
362144966Svkashyap		ccb_h->status = CAM_UA_ABORT;
363144966Svkashyap		xpt_done(ccb);
364144966Svkashyap		break;
365144966Svkashyap
366144966Svkashyap	case XPT_RESET_BUS:
367144966Svkashyap		tw_cl_create_event(&(sc->ctlr_handle), TW_CL_TRUE,
368144966Svkashyap			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
369144966Svkashyap			0x2108, 0x3, TW_CL_SEVERITY_INFO_STRING,
370144966Svkashyap			"Received Reset Bus request from CAM",
371144966Svkashyap			" ");
372144966Svkashyap
373172496Sscottl		mtx_unlock(sc->sim_lock);
374144966Svkashyap		if (tw_cl_reset_ctlr(&sc->ctlr_handle)) {
375144966Svkashyap			tw_cl_create_event(&(sc->ctlr_handle), TW_CL_TRUE,
376144966Svkashyap				TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
377144966Svkashyap				0x2109, 0x1, TW_CL_SEVERITY_ERROR_STRING,
378144966Svkashyap				"Failed to reset bus",
379144966Svkashyap				" ");
380144966Svkashyap			ccb_h->status = CAM_REQ_CMP_ERR;
381144966Svkashyap		}
382144966Svkashyap		else
383144966Svkashyap			ccb_h->status = CAM_REQ_CMP;
384144966Svkashyap
385172496Sscottl		mtx_lock(sc->sim_lock);
386144966Svkashyap		xpt_done(ccb);
387144966Svkashyap		break;
388144966Svkashyap
389144966Svkashyap	case XPT_SET_TRAN_SETTINGS:
390144966Svkashyap		tw_osli_dbg_dprintf(3, sc, "XPT_SET_TRAN_SETTINGS");
391144966Svkashyap
392144966Svkashyap		/*
393144966Svkashyap		 * This command is not supported, since it's very specific
394144966Svkashyap		 * to SCSI, and we are doing ATA.
395144966Svkashyap		 */
396144966Svkashyap  		ccb_h->status = CAM_FUNC_NOTAVAIL;
397144966Svkashyap  		xpt_done(ccb);
398144966Svkashyap  		break;
399144966Svkashyap
400144966Svkashyap	case XPT_GET_TRAN_SETTINGS:
401144966Svkashyap	{
402144966Svkashyap		struct ccb_trans_settings	*cts = &ccb->cts;
403163816Smjacob		struct ccb_trans_settings_scsi *scsi =
404163816Smjacob		    &cts->proto_specific.scsi;
405163816Smjacob		struct ccb_trans_settings_spi *spi =
406163816Smjacob		    &cts->xport_specific.spi;
407144966Svkashyap
408163816Smjacob		cts->protocol = PROTO_SCSI;
409163816Smjacob		cts->protocol_version = SCSI_REV_2;
410163816Smjacob		cts->transport = XPORT_SPI;
411163816Smjacob		cts->transport_version = 2;
412163816Smjacob
413163816Smjacob		spi->valid = CTS_SPI_VALID_DISC;
414163816Smjacob		spi->flags = CTS_SPI_FLAGS_DISC_ENB;
415163816Smjacob		scsi->valid = CTS_SCSI_VALID_TQ;
416163816Smjacob		scsi->flags = CTS_SCSI_FLAGS_TAG_ENB;
417163816Smjacob		tw_osli_dbg_dprintf(3, sc, "XPT_GET_TRAN_SETTINGS");
418144966Svkashyap		ccb_h->status = CAM_REQ_CMP;
419144966Svkashyap		xpt_done(ccb);
420144966Svkashyap		break;
421144966Svkashyap	}
422144966Svkashyap
423144966Svkashyap	case XPT_CALC_GEOMETRY:
424144966Svkashyap		tw_osli_dbg_dprintf(3, sc, "XPT_CALC_GEOMETRY");
425144966Svkashyap		cam_calc_geometry(&ccb->ccg, 1/* extended */);
426144966Svkashyap		xpt_done(ccb);
427144966Svkashyap		break;
428144966Svkashyap
429144966Svkashyap	case XPT_PATH_INQ:    /* Path inquiry -- get twa properties */
430144966Svkashyap	{
431144966Svkashyap		struct ccb_pathinq	*path_inq = &ccb->cpi;
432144966Svkashyap
433144966Svkashyap		tw_osli_dbg_dprintf(3, sc, "XPT_PATH_INQ request");
434144966Svkashyap
435144966Svkashyap		path_inq->version_num = 1;
436144966Svkashyap		path_inq->hba_inquiry = 0;
437144966Svkashyap		path_inq->target_sprt = 0;
438144966Svkashyap		path_inq->hba_misc = 0;
439144966Svkashyap		path_inq->hba_eng_cnt = 0;
440144966Svkashyap		path_inq->max_target = TW_CL_MAX_NUM_UNITS;
441144966Svkashyap		path_inq->max_lun = TW_CL_MAX_NUM_LUNS - 1;
442144966Svkashyap		path_inq->unit_number = cam_sim_unit(sim);
443144966Svkashyap		path_inq->bus_id = cam_sim_bus(sim);
444152213Svkashyap		path_inq->initiator_id = TW_CL_MAX_NUM_UNITS;
445144966Svkashyap		path_inq->base_transfer_speed = 100000;
446144966Svkashyap		strncpy(path_inq->sim_vid, "FreeBSD", SIM_IDLEN);
447144966Svkashyap		strncpy(path_inq->hba_vid, "3ware", HBA_IDLEN);
448144966Svkashyap		strncpy(path_inq->dev_name, cam_sim_name(sim), DEV_IDLEN);
449163816Smjacob                path_inq->transport = XPORT_SPI;
450163816Smjacob                path_inq->transport_version = 2;
451163816Smjacob                path_inq->protocol = PROTO_SCSI;
452163816Smjacob                path_inq->protocol_version = SCSI_REV_2;
453144966Svkashyap		ccb_h->status = CAM_REQ_CMP;
454144966Svkashyap		xpt_done(ccb);
455144966Svkashyap		break;
456144966Svkashyap	}
457144966Svkashyap
458144966Svkashyap	default:
459144966Svkashyap		tw_osli_dbg_dprintf(3, sc, "func_code = %x", ccb_h->func_code);
460144966Svkashyap		ccb_h->status = CAM_REQ_INVALID;
461144966Svkashyap		xpt_done(ccb);
462144966Svkashyap		break;
463144966Svkashyap	}
464144966Svkashyap}
465144966Svkashyap
466144966Svkashyap
467144966Svkashyap
468144966Svkashyap/*
469144966Svkashyap * Function name:	twa_poll
470144966Svkashyap * Description:		Driver entry point called when interrupts are not
471144966Svkashyap *			available.
472144966Svkashyap *
473144966Svkashyap * Input:		sim	-- sim corresponding to the controller
474144966Svkashyap * Output:		None
475144966Svkashyap * Return value:	None
476144966Svkashyap */
477144966SvkashyapTW_VOID
478144966Svkashyaptwa_poll(struct cam_sim *sim)
479144966Svkashyap{
480144966Svkashyap	struct twa_softc *sc = (struct twa_softc *)(cam_sim_softc(sim));
481144966Svkashyap
482144966Svkashyap	tw_osli_dbg_dprintf(3, sc, "entering; sc = %p", sc);
483145688Svkashyap	tw_cl_interrupt(&(sc->ctlr_handle));
484144966Svkashyap	tw_osli_dbg_dprintf(3, sc, "exiting; sc = %p", sc);
485144966Svkashyap}
486144966Svkashyap
487144966Svkashyap
488144966Svkashyap
489144966Svkashyap/*
490144966Svkashyap * Function name:	twa_timeout
491144966Svkashyap * Description:		Driver entry point for being alerted on a request
492144966Svkashyap *			timing out.
493144966Svkashyap *
494144966Svkashyap * Input:		arg	-- ptr to timed out request
495144966Svkashyap * Output:		None
496144966Svkashyap * Return value:	None
497144966Svkashyap */
498144966Svkashyapstatic TW_VOID
499144966Svkashyaptwa_timeout(TW_VOID *arg)
500144966Svkashyap{
501144966Svkashyap	struct tw_osli_req_context	*req =
502144966Svkashyap		(struct tw_osli_req_context *)arg;
503144966Svkashyap
504144966Svkashyap	tw_cl_create_event(&(req->ctlr->ctlr_handle), TW_CL_TRUE,
505144966Svkashyap		TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
506144966Svkashyap		0x210B, 0x1, TW_CL_SEVERITY_ERROR_STRING,
507144966Svkashyap		"Request timed out!",
508144966Svkashyap		"request = %p", req);
509144966Svkashyap	tw_cl_reset_ctlr(&(req->ctlr->ctlr_handle));
510144966Svkashyap}
511144966Svkashyap
512144966Svkashyap
513144966Svkashyap
514144966Svkashyap/*
515144966Svkashyap * Function name:	tw_osli_request_bus_scan
516144966Svkashyap * Description:		Requests CAM for a scan of the bus.
517144966Svkashyap *
518144966Svkashyap * Input:		sc	-- ptr to per ctlr structure
519144966Svkashyap * Output:		None
520144966Svkashyap * Return value:	0	-- success
521144966Svkashyap *			non-zero-- failure
522144966Svkashyap */
523144966SvkashyapTW_INT32
524144966Svkashyaptw_osli_request_bus_scan(struct twa_softc *sc)
525144966Svkashyap{
526144966Svkashyap	union ccb	*ccb;
527144966Svkashyap
528144966Svkashyap	tw_osli_dbg_dprintf(3, sc, "entering");
529144966Svkashyap
530152213Svkashyap	/* If we get here before sc->sim is initialized, return an error. */
531152213Svkashyap	if (!(sc->sim))
532152213Svkashyap		return(ENXIO);
533203108Smav	if ((ccb = xpt_alloc_ccb()) == NULL)
534144966Svkashyap		return(ENOMEM);
535172496Sscottl	mtx_lock(sc->sim_lock);
536203108Smav	if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, cam_sim_path(sc->sim),
537203108Smav	    CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
538203108Smav		xpt_free_ccb(ccb);
539172496Sscottl		mtx_unlock(sc->sim_lock);
540144966Svkashyap		return(EIO);
541169400Sscottl	}
542144966Svkashyap
543203108Smav	xpt_rescan(ccb);
544172496Sscottl	mtx_unlock(sc->sim_lock);
545144966Svkashyap	return(0);
546144966Svkashyap}
547144966Svkashyap
548144966Svkashyap
549144966Svkashyap
550144966Svkashyap/*
551144966Svkashyap * Function name:	tw_osli_disallow_new_requests
552144966Svkashyap * Description:		Calls the appropriate CAM function, so as to freeze
553144966Svkashyap *			the flow of new requests from CAM to this controller.
554144966Svkashyap *
555144966Svkashyap * Input:		sc	-- ptr to OSL internal ctlr context
556208969Sdelphij *			req_handle -- ptr to request handle sent by OSL.
557144966Svkashyap * Output:		None
558144966Svkashyap * Return value:	None
559144966Svkashyap */
560144966SvkashyapTW_VOID
561208969Sdelphijtw_osli_disallow_new_requests(struct twa_softc *sc,
562208969Sdelphij	struct tw_cl_req_handle *req_handle)
563144966Svkashyap{
564208969Sdelphij	/* Only freeze/release the simq for IOs */
565208969Sdelphij	if (req_handle->is_io) {
566208969Sdelphij		struct tw_osli_req_context	*req = req_handle->osl_req_ctxt;
567208969Sdelphij		union ccb			*ccb = (union ccb *)(req->orig_req);
568208969Sdelphij
569172496Sscottl		xpt_freeze_simq(sc->sim, 1);
570208969Sdelphij		ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
571172496Sscottl	}
572144966Svkashyap}
573144966Svkashyap
574144966Svkashyap
575144966Svkashyap
576144966Svkashyap/*
577152213Svkashyap * Function name:	tw_osl_ctlr_busy
578152213Svkashyap * Description:		CL calls this function on cmd queue full or otherwise,
579152213Svkashyap *			when it is too busy to accept new requests.
580152213Svkashyap *
581152213Svkashyap * Input:		ctlr_handle	-- ptr to controller handle
582152213Svkashyap *			req_handle	-- ptr to request handle sent by OSL.
583152213Svkashyap * Output:		None
584152213Svkashyap * Return value:	None
585152213Svkashyap */
586152213SvkashyapTW_VOID
587152213Svkashyaptw_osl_ctlr_busy(struct tw_cl_ctlr_handle *ctlr_handle,
588152213Svkashyap	struct tw_cl_req_handle *req_handle)
589152213Svkashyap{
590208969Sdelphij	tw_osli_disallow_new_requests(ctlr_handle->osl_ctlr_ctxt, req_handle);
591152213Svkashyap}
592152213Svkashyap
593152213Svkashyap
594152213Svkashyap
595152213Svkashyap/*
596144966Svkashyap * Function name:	tw_osl_scan_bus
597144966Svkashyap * Description:		CL calls this function to request for a bus scan.
598144966Svkashyap *
599144966Svkashyap * Input:		ctlr_handle	-- ptr to controller handle
600144966Svkashyap * Output:		None
601144966Svkashyap * Return value:	None
602144966Svkashyap */
603144966SvkashyapTW_VOID
604144966Svkashyaptw_osl_scan_bus(struct tw_cl_ctlr_handle *ctlr_handle)
605144966Svkashyap{
606144966Svkashyap	struct twa_softc	*sc = ctlr_handle->osl_ctlr_ctxt;
607144966Svkashyap	TW_INT32		error;
608144966Svkashyap
609144966Svkashyap	if ((error = tw_osli_request_bus_scan(sc)))
610144966Svkashyap		tw_osli_printf(sc, "error = %d",
611144966Svkashyap			TW_CL_SEVERITY_ERROR_STRING,
612144966Svkashyap			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
613144966Svkashyap			0x2109,
614144966Svkashyap			"Bus scan request to CAM failed",
615144966Svkashyap			error);
616144966Svkashyap}
617144966Svkashyap
618144966Svkashyap
619144966Svkashyap
620144966Svkashyap/*
621144966Svkashyap * Function name:	tw_osl_complete_io
622144966Svkashyap * Description:		Called to complete CAM scsi requests.
623144966Svkashyap *
624144966Svkashyap * Input:		req_handle	-- ptr to request handle
625144966Svkashyap * Output:		None
626144966Svkashyap * Return value:	None
627144966Svkashyap */
628144966SvkashyapTW_VOID
629144966Svkashyaptw_osl_complete_io(struct tw_cl_req_handle *req_handle)
630144966Svkashyap{
631144966Svkashyap	struct tw_osli_req_context	*req = req_handle->osl_req_ctxt;
632144966Svkashyap	struct tw_cl_req_packet		*req_pkt =
633144966Svkashyap		(struct tw_cl_req_packet *)(&req->req_pkt);
634144966Svkashyap	struct tw_cl_scsi_req_packet	*scsi_req;
635144966Svkashyap	struct twa_softc		*sc = req->ctlr;
636144966Svkashyap	union ccb			*ccb = (union ccb *)(req->orig_req);
637144966Svkashyap
638144966Svkashyap	tw_osli_dbg_dprintf(10, sc, "entering");
639144966Svkashyap
640144966Svkashyap	if (req->state != TW_OSLI_REQ_STATE_BUSY)
641144966Svkashyap		tw_osli_printf(sc, "request = %p, status = %d",
642144966Svkashyap			TW_CL_SEVERITY_ERROR_STRING,
643144966Svkashyap			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
644144966Svkashyap			0x210A,
645144966Svkashyap			"Unposted command completed!!",
646144966Svkashyap			req, req->state);
647144966Svkashyap
648144966Svkashyap	/*
649144966Svkashyap	 * Remove request from the busy queue.  Just mark it complete.
650144966Svkashyap	 * There's no need to move it into the complete queue as we are
651144966Svkashyap	 * going to be done with it right now.
652144966Svkashyap	 */
653144966Svkashyap	req->state = TW_OSLI_REQ_STATE_COMPLETE;
654144966Svkashyap	tw_osli_req_q_remove_item(req, TW_OSLI_BUSY_Q);
655144966Svkashyap
656144966Svkashyap	tw_osli_unmap_request(req);
657144966Svkashyap
658144966Svkashyap	untimeout(twa_timeout, req, ccb->ccb_h.timeout_ch);
659144966Svkashyap	if (req->error_code) {
660144966Svkashyap		/* This request never got submitted to the firmware. */
661144966Svkashyap		if (req->error_code == EBUSY) {
662144966Svkashyap			/*
663152213Svkashyap			 * Cmd queue is full, or the Common Layer is out of
664208969Sdelphij			 * resources.  The simq will already have been frozen.
665208969Sdelphij			 * When this ccb gets completed will unfreeze the simq.
666144966Svkashyap			 */
667144966Svkashyap			ccb->ccb_h.status |= CAM_REQUEUE_REQ;
668144966Svkashyap		}
669144966Svkashyap		else if (req->error_code == EFBIG)
670144966Svkashyap			ccb->ccb_h.status = CAM_REQ_TOO_BIG;
671144966Svkashyap		else
672144966Svkashyap			ccb->ccb_h.status = CAM_REQ_CMP_ERR;
673144966Svkashyap	} else {
674144966Svkashyap		scsi_req = &(req_pkt->gen_req_pkt.scsi_req);
675144966Svkashyap		if (req_pkt->status == TW_CL_ERR_REQ_SUCCESS)
676144966Svkashyap			ccb->ccb_h.status = CAM_REQ_CMP;
677144966Svkashyap		else {
678144966Svkashyap			if (req_pkt->status & TW_CL_ERR_REQ_INVALID_TARGET)
679144966Svkashyap				ccb->ccb_h.status |= CAM_TID_INVALID;
680144966Svkashyap			else if (req_pkt->status & TW_CL_ERR_REQ_INVALID_LUN)
681144966Svkashyap				ccb->ccb_h.status |= CAM_LUN_INVALID;
682144966Svkashyap			else if (req_pkt->status & TW_CL_ERR_REQ_SCSI_ERROR)
683144966Svkashyap				ccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
684144966Svkashyap			else if (req_pkt->status & TW_CL_ERR_REQ_BUS_RESET)
685144966Svkashyap				ccb->ccb_h.status |= CAM_SCSI_BUS_RESET;
686144966Svkashyap			/*
687144966Svkashyap			 * If none of the above errors occurred, simply
688144966Svkashyap			 * mark completion error.
689144966Svkashyap			 */
690144966Svkashyap			if (ccb->ccb_h.status == 0)
691144966Svkashyap				ccb->ccb_h.status = CAM_REQ_CMP_ERR;
692144966Svkashyap
693144966Svkashyap			if (req_pkt->status & TW_CL_ERR_REQ_AUTO_SENSE_VALID) {
694144966Svkashyap				ccb->csio.sense_len = scsi_req->sense_len;
695144966Svkashyap				ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
696144966Svkashyap			}
697144966Svkashyap		}
698144966Svkashyap
699144966Svkashyap		ccb->csio.scsi_status = scsi_req->scsi_status;
700144966Svkashyap	}
701144966Svkashyap
702144966Svkashyap	ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
703172496Sscottl	mtx_lock(sc->sim_lock);
704144966Svkashyap	xpt_done(ccb);
705172496Sscottl	mtx_unlock(sc->sim_lock);
706144966Svkashyap	if (! req->error_code)
707144966Svkashyap		 /* twa_action will free the request otherwise */
708144966Svkashyap		tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q);
709144966Svkashyap}
710144966Svkashyap
711