tw_osl_cam.c revision 246713
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 246713 2013-02-12 16:57:20Z kib $
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);
58144966Svkashyap
59144966Svkashyapstatic TW_INT32	tw_osli_execute_scsi(struct tw_osli_req_context *req,
60144966Svkashyap	union ccb *ccb);
61144966Svkashyap
62144966Svkashyap
63144966Svkashyap
64144966Svkashyap/*
65144966Svkashyap * Function name:	tw_osli_cam_attach
66144966Svkashyap * Description:		Attaches the driver to CAM.
67144966Svkashyap *
68144966Svkashyap * Input:		sc	-- ptr to OSL internal ctlr context
69144966Svkashyap * Output:		None
70144966Svkashyap * Return value:	0	-- success
71144966Svkashyap *			non-zero-- failure
72144966Svkashyap */
73144966SvkashyapTW_INT32
74144966Svkashyaptw_osli_cam_attach(struct twa_softc *sc)
75144966Svkashyap{
76144966Svkashyap	struct cam_devq		*devq;
77144966Svkashyap
78144966Svkashyap	tw_osli_dbg_dprintf(3, sc, "entered");
79144966Svkashyap
80144966Svkashyap	/*
81144966Svkashyap	 * Create the device queue for our SIM.
82144966Svkashyap	 */
83212008Sdelphij	if ((devq = cam_simq_alloc(TW_OSLI_MAX_NUM_IOS)) == NULL) {
84144966Svkashyap		tw_osli_printf(sc, "error = %d",
85144966Svkashyap			TW_CL_SEVERITY_ERROR_STRING,
86144966Svkashyap			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
87144966Svkashyap			0x2100,
88144966Svkashyap			"Failed to create SIM device queue",
89144966Svkashyap			ENOMEM);
90144966Svkashyap		return(ENOMEM);
91144966Svkashyap	}
92144966Svkashyap
93144966Svkashyap	/*
94208969Sdelphij	 * Create a SIM entry.  Though we can support TW_OSLI_MAX_NUM_REQUESTS
95144966Svkashyap	 * simultaneous requests, we claim to be able to handle only
96208969Sdelphij	 * TW_OSLI_MAX_NUM_IOS (two less), so that we always have a request
97208969Sdelphij	 * packet available to service ioctls and AENs.
98144966Svkashyap	 */
99144966Svkashyap	tw_osli_dbg_dprintf(3, sc, "Calling cam_sim_alloc");
100144966Svkashyap	sc->sim = cam_sim_alloc(twa_action, twa_poll, "twa", sc,
101172496Sscottl			device_get_unit(sc->bus_dev), sc->sim_lock,
102208969Sdelphij			TW_OSLI_MAX_NUM_IOS, 1, devq);
103144966Svkashyap	if (sc->sim == NULL) {
104144966Svkashyap		cam_simq_free(devq);
105144966Svkashyap		tw_osli_printf(sc, "error = %d",
106144966Svkashyap			TW_CL_SEVERITY_ERROR_STRING,
107144966Svkashyap			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
108144966Svkashyap			0x2101,
109144966Svkashyap			"Failed to create a SIM entry",
110144966Svkashyap			ENOMEM);
111144966Svkashyap		return(ENOMEM);
112144966Svkashyap	}
113144966Svkashyap
114144966Svkashyap	/*
115144966Svkashyap	 * Register the bus.
116144966Svkashyap	 */
117144966Svkashyap	tw_osli_dbg_dprintf(3, sc, "Calling xpt_bus_register");
118172496Sscottl	mtx_lock(sc->sim_lock);
119170872Sscottl	if (xpt_bus_register(sc->sim, sc->bus_dev, 0) != CAM_SUCCESS) {
120144966Svkashyap		cam_sim_free(sc->sim, TRUE);
121144966Svkashyap		sc->sim = NULL; /* so cam_detach will not try to free it */
122144966Svkashyap		tw_osli_printf(sc, "error = %d",
123144966Svkashyap			TW_CL_SEVERITY_ERROR_STRING,
124144966Svkashyap			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
125144966Svkashyap			0x2102,
126144966Svkashyap			"Failed to register the bus",
127144966Svkashyap			ENXIO);
128172496Sscottl		mtx_unlock(sc->sim_lock);
129144966Svkashyap		return(ENXIO);
130144966Svkashyap	}
131144966Svkashyap
132144966Svkashyap	tw_osli_dbg_dprintf(3, sc, "Calling xpt_create_path");
133144966Svkashyap	if (xpt_create_path(&sc->path, NULL,
134144966Svkashyap				cam_sim_path(sc->sim),
135144966Svkashyap				CAM_TARGET_WILDCARD,
136144966Svkashyap				CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
137144966Svkashyap		xpt_bus_deregister(cam_sim_path (sc->sim));
138144966Svkashyap		/* Passing TRUE to cam_sim_free will free the devq as well. */
139144966Svkashyap		cam_sim_free(sc->sim, TRUE);
140144966Svkashyap		tw_osli_printf(sc, "error = %d",
141144966Svkashyap			TW_CL_SEVERITY_ERROR_STRING,
142144966Svkashyap			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
143144966Svkashyap			0x2103,
144144966Svkashyap			"Failed to create path",
145144966Svkashyap			ENXIO);
146172496Sscottl		mtx_unlock(sc->sim_lock);
147144966Svkashyap		return(ENXIO);
148144966Svkashyap	}
149172496Sscottl	mtx_unlock(sc->sim_lock);
150144966Svkashyap
151144966Svkashyap	tw_osli_dbg_dprintf(3, sc, "exiting");
152144966Svkashyap	return(0);
153144966Svkashyap}
154144966Svkashyap
155144966Svkashyap
156144966Svkashyap
157144966Svkashyap/*
158144966Svkashyap * Function name:	tw_osli_cam_detach
159144966Svkashyap * Description:		Detaches the driver from CAM.
160144966Svkashyap *
161144966Svkashyap * Input:		sc	-- ptr to OSL internal ctlr context
162144966Svkashyap * Output:		None
163144966Svkashyap * Return value:	None
164144966Svkashyap */
165144966SvkashyapTW_VOID
166144966Svkashyaptw_osli_cam_detach(struct twa_softc *sc)
167144966Svkashyap{
168144966Svkashyap	tw_osli_dbg_dprintf(3, sc, "entered");
169144966Svkashyap
170172496Sscottl	mtx_lock(sc->sim_lock);
171172496Sscottl
172144966Svkashyap	if (sc->path)
173144966Svkashyap		xpt_free_path(sc->path);
174144966Svkashyap	if (sc->sim) {
175144966Svkashyap		xpt_bus_deregister(cam_sim_path(sc->sim));
176144966Svkashyap		/* Passing TRUE to cam_sim_free will free the devq as well. */
177144966Svkashyap		cam_sim_free(sc->sim, TRUE);
178144966Svkashyap	}
179172496Sscottl	/* It's ok have 1 hold count while destroying the mutex */
180172496Sscottl	mtx_destroy(sc->sim_lock);
181144966Svkashyap}
182144966Svkashyap
183144966Svkashyap
184144966Svkashyap
185144966Svkashyap/*
186144966Svkashyap * Function name:	tw_osli_execute_scsi
187144966Svkashyap * Description:		Build a fw cmd, based on a CAM style ccb, and
188144966Svkashyap *			send it down.
189144966Svkashyap *
190144966Svkashyap * Input:		req	-- ptr to OSL internal request context
191144966Svkashyap *			ccb	-- ptr to CAM style ccb
192144966Svkashyap * Output:		None
193144966Svkashyap * Return value:	0	-- success
194144966Svkashyap *			non-zero-- failure
195144966Svkashyap */
196144966SvkashyapTW_INT32
197144966Svkashyaptw_osli_execute_scsi(struct tw_osli_req_context *req, union ccb *ccb)
198144966Svkashyap{
199144966Svkashyap	struct twa_softc		*sc = req->ctlr;
200144966Svkashyap	struct tw_cl_req_packet		*req_pkt;
201144966Svkashyap	struct tw_cl_scsi_req_packet	*scsi_req;
202144966Svkashyap	struct ccb_hdr			*ccb_h = &(ccb->ccb_h);
203144966Svkashyap	struct ccb_scsiio		*csio = &(ccb->csio);
204144966Svkashyap	TW_INT32			error;
205144966Svkashyap
206144966Svkashyap	tw_osli_dbg_dprintf(10, sc, "SCSI I/O request 0x%x",
207144966Svkashyap		csio->cdb_io.cdb_bytes[0]);
208144966Svkashyap
209144966Svkashyap	if (ccb_h->target_id >= TW_CL_MAX_NUM_UNITS) {
210144966Svkashyap		tw_osli_dbg_dprintf(3, sc, "Invalid target. PTL = %x %x %x",
211144966Svkashyap			ccb_h->path_id, ccb_h->target_id, ccb_h->target_lun);
212144966Svkashyap		ccb_h->status |= CAM_TID_INVALID;
213144966Svkashyap		xpt_done(ccb);
214144966Svkashyap		return(1);
215144966Svkashyap	}
216144966Svkashyap	if (ccb_h->target_lun >= TW_CL_MAX_NUM_LUNS) {
217144966Svkashyap		tw_osli_dbg_dprintf(3, sc, "Invalid lun. PTL = %x %x %x",
218144966Svkashyap			ccb_h->path_id, ccb_h->target_id, ccb_h->target_lun);
219144966Svkashyap		ccb_h->status |= CAM_LUN_INVALID;
220144966Svkashyap		xpt_done(ccb);
221144966Svkashyap		return(1);
222144966Svkashyap	}
223144966Svkashyap
224144966Svkashyap	if(ccb_h->flags & CAM_CDB_PHYS) {
225144966Svkashyap		tw_osli_printf(sc, "",
226144966Svkashyap			TW_CL_SEVERITY_ERROR_STRING,
227144966Svkashyap			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
228144966Svkashyap			0x2105,
229144966Svkashyap			"Physical CDB address!");
230208969Sdelphij		ccb_h->status = CAM_REQ_INVALID;
231144966Svkashyap		xpt_done(ccb);
232144966Svkashyap		return(1);
233144966Svkashyap	}
234144966Svkashyap
235144966Svkashyap	/*
236144966Svkashyap	 * We are going to work on this request.  Mark it as enqueued (though
237144966Svkashyap	 * we don't actually queue it...)
238144966Svkashyap	 */
239144966Svkashyap	ccb_h->status |= CAM_SIM_QUEUED;
240144966Svkashyap
241144966Svkashyap	if((ccb_h->flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
242144966Svkashyap		if(ccb_h->flags & CAM_DIR_IN)
243144966Svkashyap			req->flags |= TW_OSLI_REQ_FLAGS_DATA_IN;
244144966Svkashyap		else
245144966Svkashyap			req->flags |= TW_OSLI_REQ_FLAGS_DATA_OUT;
246144966Svkashyap	}
247144966Svkashyap
248144966Svkashyap	/* Build the CL understood request packet for SCSI cmds. */
249144966Svkashyap	req_pkt = &req->req_pkt;
250144966Svkashyap	req_pkt->status = 0;
251144966Svkashyap	req_pkt->tw_osl_callback = tw_osl_complete_io;
252144966Svkashyap	scsi_req = &(req_pkt->gen_req_pkt.scsi_req);
253144966Svkashyap	scsi_req->unit = ccb_h->target_id;
254144966Svkashyap	scsi_req->lun = ccb_h->target_lun;
255144966Svkashyap	scsi_req->sense_len = 0;
256144966Svkashyap	scsi_req->sense_data = (TW_UINT8 *)(&csio->sense_data);
257144966Svkashyap	scsi_req->scsi_status = 0;
258144966Svkashyap	if(ccb_h->flags & CAM_CDB_POINTER)
259144966Svkashyap		scsi_req->cdb = csio->cdb_io.cdb_ptr;
260144966Svkashyap	else
261144966Svkashyap		scsi_req->cdb = csio->cdb_io.cdb_bytes;
262144966Svkashyap	scsi_req->cdb_len = csio->cdb_len;
263144966Svkashyap
264246713Skib	if (csio->dxfer_len > TW_CL_MAX_IO_SIZE) {
265246713Skib		tw_osli_printf(sc, "size = %d",
266144966Svkashyap			TW_CL_SEVERITY_ERROR_STRING,
267144966Svkashyap			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
268246713Skib			0x2106,
269246713Skib			"I/O size too big",
270246713Skib			csio->dxfer_len);
271246713Skib		ccb_h->status = CAM_REQ_TOO_BIG;
272144966Svkashyap		ccb_h->status &= ~CAM_SIM_QUEUED;
273144966Svkashyap		xpt_done(ccb);
274144966Svkashyap		return(1);
275144966Svkashyap	}
276246713Skib	req->data = ccb;
277246713Skib	req->length = csio->dxfer_len;
278246713Skib	req->flags |= TW_OSLI_REQ_FLAGS_CCB;
279212008Sdelphij	req->deadline = tw_osl_get_local_time() + (ccb_h->timeout / 1000);
280212008Sdelphij
281144966Svkashyap	/*
282144966Svkashyap	 * twa_map_load_data_callback will fill in the SGL,
283144966Svkashyap	 * and submit the I/O.
284144966Svkashyap	 */
285144966Svkashyap	error = tw_osli_map_request(req);
286212008Sdelphij	if ((error) && (req->flags & TW_OSLI_REQ_FLAGS_FAILED)) {
287212008Sdelphij		req->deadline = 0;
288212008Sdelphij		ccb_h->status = CAM_REQ_CMP_ERR;
289212008Sdelphij		ccb_h->status &= ~CAM_SIM_QUEUED;
290212008Sdelphij		xpt_done(ccb);
291212008Sdelphij	}
292144966Svkashyap	return(error);
293144966Svkashyap}
294144966Svkashyap
295144966Svkashyap
296144966Svkashyap
297144966Svkashyap/*
298144966Svkashyap * Function name:	twa_action
299144966Svkashyap * Description:		Driver entry point for CAM's use.
300144966Svkashyap *
301144966Svkashyap * Input:		sim	-- sim corresponding to the ctlr
302144966Svkashyap *			ccb	-- ptr to CAM request
303144966Svkashyap * Output:		None
304144966Svkashyap * Return value:	None
305144966Svkashyap */
306144966SvkashyapTW_VOID
307144966Svkashyaptwa_action(struct cam_sim *sim, union ccb *ccb)
308144966Svkashyap{
309144966Svkashyap	struct twa_softc	*sc = (struct twa_softc *)cam_sim_softc(sim);
310144966Svkashyap	struct ccb_hdr		*ccb_h = &(ccb->ccb_h);
311144966Svkashyap
312144966Svkashyap	switch (ccb_h->func_code) {
313144966Svkashyap	case XPT_SCSI_IO:	/* SCSI I/O */
314144966Svkashyap	{
315144966Svkashyap		struct tw_osli_req_context	*req;
316144966Svkashyap
317208969Sdelphij		req = tw_osli_get_request(sc);
318208969Sdelphij		if (req == NULL) {
319208969Sdelphij			tw_osli_dbg_dprintf(2, sc, "Cannot get request pkt.");
320144966Svkashyap			/*
321144966Svkashyap			 * Freeze the simq to maintain ccb ordering.  The next
322144966Svkashyap			 * ccb that gets completed will unfreeze the simq.
323144966Svkashyap			 */
324212008Sdelphij			ccb_h->status &= ~CAM_SIM_QUEUED;
325144966Svkashyap			ccb_h->status |= CAM_REQUEUE_REQ;
326144966Svkashyap			xpt_done(ccb);
327144966Svkashyap			break;
328144966Svkashyap		}
329212008Sdelphij
330212008Sdelphij		if ((tw_cl_is_reset_needed(&(req->ctlr->ctlr_handle)))) {
331212008Sdelphij			ccb_h->status &= ~CAM_SIM_QUEUED;
332212008Sdelphij			ccb_h->status |= CAM_REQUEUE_REQ;
333212008Sdelphij			xpt_done(ccb);
334212008Sdelphij			tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q);
335212008Sdelphij			break;
336212008Sdelphij		}
337212008Sdelphij
338144966Svkashyap		req->req_handle.osl_req_ctxt = req;
339208969Sdelphij		req->req_handle.is_io = TW_CL_TRUE;
340144966Svkashyap		req->orig_req = ccb;
341144966Svkashyap		if (tw_osli_execute_scsi(req, ccb))
342144966Svkashyap			tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q);
343144966Svkashyap		break;
344144966Svkashyap	}
345144966Svkashyap
346144966Svkashyap	case XPT_ABORT:
347144966Svkashyap		tw_osli_dbg_dprintf(2, sc, "Abort request.");
348144966Svkashyap		ccb_h->status = CAM_UA_ABORT;
349144966Svkashyap		xpt_done(ccb);
350144966Svkashyap		break;
351144966Svkashyap
352144966Svkashyap	case XPT_RESET_BUS:
353212008Sdelphij		tw_cl_create_event(&(sc->ctlr_handle), TW_CL_FALSE,
354144966Svkashyap			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
355144966Svkashyap			0x2108, 0x3, TW_CL_SEVERITY_INFO_STRING,
356144966Svkashyap			"Received Reset Bus request from CAM",
357144966Svkashyap			" ");
358144966Svkashyap
359212008Sdelphij		tw_cl_set_reset_needed(&(sc->ctlr_handle));
360212008Sdelphij		ccb_h->status = CAM_REQ_CMP;
361144966Svkashyap		xpt_done(ccb);
362144966Svkashyap		break;
363144966Svkashyap
364144966Svkashyap	case XPT_SET_TRAN_SETTINGS:
365144966Svkashyap		tw_osli_dbg_dprintf(3, sc, "XPT_SET_TRAN_SETTINGS");
366144966Svkashyap
367144966Svkashyap		/*
368144966Svkashyap		 * This command is not supported, since it's very specific
369144966Svkashyap		 * to SCSI, and we are doing ATA.
370144966Svkashyap		 */
371144966Svkashyap  		ccb_h->status = CAM_FUNC_NOTAVAIL;
372144966Svkashyap  		xpt_done(ccb);
373144966Svkashyap  		break;
374144966Svkashyap
375144966Svkashyap	case XPT_GET_TRAN_SETTINGS:
376144966Svkashyap	{
377144966Svkashyap		struct ccb_trans_settings	*cts = &ccb->cts;
378163816Smjacob		struct ccb_trans_settings_scsi *scsi =
379163816Smjacob		    &cts->proto_specific.scsi;
380163816Smjacob		struct ccb_trans_settings_spi *spi =
381163816Smjacob		    &cts->xport_specific.spi;
382144966Svkashyap
383163816Smjacob		cts->protocol = PROTO_SCSI;
384163816Smjacob		cts->protocol_version = SCSI_REV_2;
385163816Smjacob		cts->transport = XPORT_SPI;
386163816Smjacob		cts->transport_version = 2;
387163816Smjacob
388163816Smjacob		spi->valid = CTS_SPI_VALID_DISC;
389163816Smjacob		spi->flags = CTS_SPI_FLAGS_DISC_ENB;
390163816Smjacob		scsi->valid = CTS_SCSI_VALID_TQ;
391163816Smjacob		scsi->flags = CTS_SCSI_FLAGS_TAG_ENB;
392163816Smjacob		tw_osli_dbg_dprintf(3, sc, "XPT_GET_TRAN_SETTINGS");
393144966Svkashyap		ccb_h->status = CAM_REQ_CMP;
394144966Svkashyap		xpt_done(ccb);
395144966Svkashyap		break;
396144966Svkashyap	}
397144966Svkashyap
398144966Svkashyap	case XPT_CALC_GEOMETRY:
399144966Svkashyap		tw_osli_dbg_dprintf(3, sc, "XPT_CALC_GEOMETRY");
400144966Svkashyap		cam_calc_geometry(&ccb->ccg, 1/* extended */);
401144966Svkashyap		xpt_done(ccb);
402144966Svkashyap		break;
403144966Svkashyap
404144966Svkashyap	case XPT_PATH_INQ:    /* Path inquiry -- get twa properties */
405144966Svkashyap	{
406144966Svkashyap		struct ccb_pathinq	*path_inq = &ccb->cpi;
407144966Svkashyap
408144966Svkashyap		tw_osli_dbg_dprintf(3, sc, "XPT_PATH_INQ request");
409144966Svkashyap
410144966Svkashyap		path_inq->version_num = 1;
411144966Svkashyap		path_inq->hba_inquiry = 0;
412144966Svkashyap		path_inq->target_sprt = 0;
413144966Svkashyap		path_inq->hba_misc = 0;
414144966Svkashyap		path_inq->hba_eng_cnt = 0;
415144966Svkashyap		path_inq->max_target = TW_CL_MAX_NUM_UNITS;
416144966Svkashyap		path_inq->max_lun = TW_CL_MAX_NUM_LUNS - 1;
417144966Svkashyap		path_inq->unit_number = cam_sim_unit(sim);
418144966Svkashyap		path_inq->bus_id = cam_sim_bus(sim);
419152213Svkashyap		path_inq->initiator_id = TW_CL_MAX_NUM_UNITS;
420144966Svkashyap		path_inq->base_transfer_speed = 100000;
421144966Svkashyap		strncpy(path_inq->sim_vid, "FreeBSD", SIM_IDLEN);
422144966Svkashyap		strncpy(path_inq->hba_vid, "3ware", HBA_IDLEN);
423144966Svkashyap		strncpy(path_inq->dev_name, cam_sim_name(sim), DEV_IDLEN);
424163816Smjacob                path_inq->transport = XPORT_SPI;
425163816Smjacob                path_inq->transport_version = 2;
426163816Smjacob                path_inq->protocol = PROTO_SCSI;
427163816Smjacob                path_inq->protocol_version = SCSI_REV_2;
428212008Sdelphij                path_inq->maxio = TW_CL_MAX_IO_SIZE;
429144966Svkashyap		ccb_h->status = CAM_REQ_CMP;
430144966Svkashyap		xpt_done(ccb);
431144966Svkashyap		break;
432144966Svkashyap	}
433144966Svkashyap
434144966Svkashyap	default:
435144966Svkashyap		tw_osli_dbg_dprintf(3, sc, "func_code = %x", ccb_h->func_code);
436144966Svkashyap		ccb_h->status = CAM_REQ_INVALID;
437144966Svkashyap		xpt_done(ccb);
438144966Svkashyap		break;
439144966Svkashyap	}
440144966Svkashyap}
441144966Svkashyap
442144966Svkashyap
443144966Svkashyap
444144966Svkashyap/*
445144966Svkashyap * Function name:	twa_poll
446144966Svkashyap * Description:		Driver entry point called when interrupts are not
447144966Svkashyap *			available.
448144966Svkashyap *
449144966Svkashyap * Input:		sim	-- sim corresponding to the controller
450144966Svkashyap * Output:		None
451144966Svkashyap * Return value:	None
452144966Svkashyap */
453144966SvkashyapTW_VOID
454144966Svkashyaptwa_poll(struct cam_sim *sim)
455144966Svkashyap{
456144966Svkashyap	struct twa_softc *sc = (struct twa_softc *)(cam_sim_softc(sim));
457144966Svkashyap
458144966Svkashyap	tw_osli_dbg_dprintf(3, sc, "entering; sc = %p", sc);
459145688Svkashyap	tw_cl_interrupt(&(sc->ctlr_handle));
460144966Svkashyap	tw_osli_dbg_dprintf(3, sc, "exiting; sc = %p", sc);
461144966Svkashyap}
462144966Svkashyap
463144966Svkashyap
464144966Svkashyap
465144966Svkashyap/*
466144966Svkashyap * Function name:	tw_osli_request_bus_scan
467144966Svkashyap * Description:		Requests CAM for a scan of the bus.
468144966Svkashyap *
469144966Svkashyap * Input:		sc	-- ptr to per ctlr structure
470144966Svkashyap * Output:		None
471144966Svkashyap * Return value:	0	-- success
472144966Svkashyap *			non-zero-- failure
473144966Svkashyap */
474144966SvkashyapTW_INT32
475144966Svkashyaptw_osli_request_bus_scan(struct twa_softc *sc)
476144966Svkashyap{
477144966Svkashyap	union ccb	*ccb;
478144966Svkashyap
479144966Svkashyap	tw_osli_dbg_dprintf(3, sc, "entering");
480144966Svkashyap
481152213Svkashyap	/* If we get here before sc->sim is initialized, return an error. */
482152213Svkashyap	if (!(sc->sim))
483152213Svkashyap		return(ENXIO);
484203108Smav	if ((ccb = xpt_alloc_ccb()) == NULL)
485144966Svkashyap		return(ENOMEM);
486172496Sscottl	mtx_lock(sc->sim_lock);
487203108Smav	if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, cam_sim_path(sc->sim),
488203108Smav	    CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
489203108Smav		xpt_free_ccb(ccb);
490172496Sscottl		mtx_unlock(sc->sim_lock);
491144966Svkashyap		return(EIO);
492169400Sscottl	}
493144966Svkashyap
494203108Smav	xpt_rescan(ccb);
495172496Sscottl	mtx_unlock(sc->sim_lock);
496144966Svkashyap	return(0);
497144966Svkashyap}
498144966Svkashyap
499144966Svkashyap
500144966Svkashyap
501144966Svkashyap/*
502144966Svkashyap * Function name:	tw_osli_disallow_new_requests
503144966Svkashyap * Description:		Calls the appropriate CAM function, so as to freeze
504144966Svkashyap *			the flow of new requests from CAM to this controller.
505144966Svkashyap *
506144966Svkashyap * Input:		sc	-- ptr to OSL internal ctlr context
507208969Sdelphij *			req_handle -- ptr to request handle sent by OSL.
508144966Svkashyap * Output:		None
509144966Svkashyap * Return value:	None
510144966Svkashyap */
511144966SvkashyapTW_VOID
512208969Sdelphijtw_osli_disallow_new_requests(struct twa_softc *sc,
513208969Sdelphij	struct tw_cl_req_handle *req_handle)
514144966Svkashyap{
515208969Sdelphij	/* Only freeze/release the simq for IOs */
516208969Sdelphij	if (req_handle->is_io) {
517208969Sdelphij		struct tw_osli_req_context	*req = req_handle->osl_req_ctxt;
518208969Sdelphij		union ccb			*ccb = (union ccb *)(req->orig_req);
519208969Sdelphij
520172496Sscottl		xpt_freeze_simq(sc->sim, 1);
521208969Sdelphij		ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
522172496Sscottl	}
523144966Svkashyap}
524144966Svkashyap
525144966Svkashyap
526144966Svkashyap
527144966Svkashyap/*
528212008Sdelphij * Function name:	tw_osl_timeout
529212008Sdelphij * Description:		Call to timeout().
530152213Svkashyap *
531212008Sdelphij * Input:		req_handle -- ptr to request handle sent by OSL.
532152213Svkashyap * Output:		None
533152213Svkashyap * Return value:	None
534152213Svkashyap */
535152213SvkashyapTW_VOID
536212008Sdelphijtw_osl_timeout(struct tw_cl_req_handle *req_handle)
537152213Svkashyap{
538212008Sdelphij	struct tw_osli_req_context	*req = req_handle->osl_req_ctxt;
539212008Sdelphij	union ccb			*ccb = (union ccb *)(req->orig_req);
540212008Sdelphij	struct ccb_hdr			*ccb_h = &(ccb->ccb_h);
541212008Sdelphij
542212008Sdelphij	req->deadline = tw_osl_get_local_time() + (ccb_h->timeout / 1000);
543152213Svkashyap}
544152213Svkashyap
545152213Svkashyap
546152213Svkashyap
547152213Svkashyap/*
548212008Sdelphij * Function name:	tw_osl_untimeout
549212008Sdelphij * Description:		Inverse of call to timeout().
550212008Sdelphij *
551212008Sdelphij * Input:		req_handle -- ptr to request handle sent by OSL.
552212008Sdelphij * Output:		None
553212008Sdelphij * Return value:	None
554212008Sdelphij */
555212008SdelphijTW_VOID
556212008Sdelphijtw_osl_untimeout(struct tw_cl_req_handle *req_handle)
557212008Sdelphij{
558212008Sdelphij	struct tw_osli_req_context	*req = req_handle->osl_req_ctxt;
559212008Sdelphij
560212008Sdelphij	req->deadline = 0;
561212008Sdelphij}
562212008Sdelphij
563212008Sdelphij
564212008Sdelphij
565212008Sdelphij/*
566144966Svkashyap * Function name:	tw_osl_scan_bus
567144966Svkashyap * Description:		CL calls this function to request for a bus scan.
568144966Svkashyap *
569144966Svkashyap * Input:		ctlr_handle	-- ptr to controller handle
570144966Svkashyap * Output:		None
571144966Svkashyap * Return value:	None
572144966Svkashyap */
573144966SvkashyapTW_VOID
574144966Svkashyaptw_osl_scan_bus(struct tw_cl_ctlr_handle *ctlr_handle)
575144966Svkashyap{
576144966Svkashyap	struct twa_softc	*sc = ctlr_handle->osl_ctlr_ctxt;
577144966Svkashyap	TW_INT32		error;
578144966Svkashyap
579144966Svkashyap	if ((error = tw_osli_request_bus_scan(sc)))
580144966Svkashyap		tw_osli_printf(sc, "error = %d",
581144966Svkashyap			TW_CL_SEVERITY_ERROR_STRING,
582144966Svkashyap			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
583144966Svkashyap			0x2109,
584144966Svkashyap			"Bus scan request to CAM failed",
585144966Svkashyap			error);
586144966Svkashyap}
587144966Svkashyap
588144966Svkashyap
589144966Svkashyap
590144966Svkashyap/*
591144966Svkashyap * Function name:	tw_osl_complete_io
592144966Svkashyap * Description:		Called to complete CAM scsi requests.
593144966Svkashyap *
594144966Svkashyap * Input:		req_handle	-- ptr to request handle
595144966Svkashyap * Output:		None
596144966Svkashyap * Return value:	None
597144966Svkashyap */
598144966SvkashyapTW_VOID
599144966Svkashyaptw_osl_complete_io(struct tw_cl_req_handle *req_handle)
600144966Svkashyap{
601144966Svkashyap	struct tw_osli_req_context	*req = req_handle->osl_req_ctxt;
602144966Svkashyap	struct tw_cl_req_packet		*req_pkt =
603144966Svkashyap		(struct tw_cl_req_packet *)(&req->req_pkt);
604144966Svkashyap	struct tw_cl_scsi_req_packet	*scsi_req;
605144966Svkashyap	struct twa_softc		*sc = req->ctlr;
606144966Svkashyap	union ccb			*ccb = (union ccb *)(req->orig_req);
607144966Svkashyap
608144966Svkashyap	tw_osli_dbg_dprintf(10, sc, "entering");
609144966Svkashyap
610144966Svkashyap	if (req->state != TW_OSLI_REQ_STATE_BUSY)
611144966Svkashyap		tw_osli_printf(sc, "request = %p, status = %d",
612144966Svkashyap			TW_CL_SEVERITY_ERROR_STRING,
613144966Svkashyap			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
614144966Svkashyap			0x210A,
615144966Svkashyap			"Unposted command completed!!",
616144966Svkashyap			req, req->state);
617144966Svkashyap
618144966Svkashyap	/*
619144966Svkashyap	 * Remove request from the busy queue.  Just mark it complete.
620144966Svkashyap	 * There's no need to move it into the complete queue as we are
621144966Svkashyap	 * going to be done with it right now.
622144966Svkashyap	 */
623144966Svkashyap	req->state = TW_OSLI_REQ_STATE_COMPLETE;
624144966Svkashyap	tw_osli_req_q_remove_item(req, TW_OSLI_BUSY_Q);
625144966Svkashyap
626144966Svkashyap	tw_osli_unmap_request(req);
627144966Svkashyap
628212008Sdelphij	req->deadline = 0;
629144966Svkashyap	if (req->error_code) {
630144966Svkashyap		/* This request never got submitted to the firmware. */
631144966Svkashyap		if (req->error_code == EBUSY) {
632144966Svkashyap			/*
633152213Svkashyap			 * Cmd queue is full, or the Common Layer is out of
634208969Sdelphij			 * resources.  The simq will already have been frozen.
635208969Sdelphij			 * When this ccb gets completed will unfreeze the simq.
636144966Svkashyap			 */
637144966Svkashyap			ccb->ccb_h.status |= CAM_REQUEUE_REQ;
638144966Svkashyap		}
639144966Svkashyap		else if (req->error_code == EFBIG)
640144966Svkashyap			ccb->ccb_h.status = CAM_REQ_TOO_BIG;
641144966Svkashyap		else
642144966Svkashyap			ccb->ccb_h.status = CAM_REQ_CMP_ERR;
643144966Svkashyap	} else {
644144966Svkashyap		scsi_req = &(req_pkt->gen_req_pkt.scsi_req);
645144966Svkashyap		if (req_pkt->status == TW_CL_ERR_REQ_SUCCESS)
646144966Svkashyap			ccb->ccb_h.status = CAM_REQ_CMP;
647144966Svkashyap		else {
648144966Svkashyap			if (req_pkt->status & TW_CL_ERR_REQ_INVALID_TARGET)
649237460Smav				ccb->ccb_h.status |= CAM_SEL_TIMEOUT;
650144966Svkashyap			else if (req_pkt->status & TW_CL_ERR_REQ_INVALID_LUN)
651237460Smav				ccb->ccb_h.status |= CAM_DEV_NOT_THERE;
652144966Svkashyap			else if (req_pkt->status & TW_CL_ERR_REQ_SCSI_ERROR)
653144966Svkashyap				ccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
654144966Svkashyap			else if (req_pkt->status & TW_CL_ERR_REQ_BUS_RESET)
655212008Sdelphij				ccb->ccb_h.status |= (CAM_REQUEUE_REQ | CAM_SCSI_BUS_RESET);
656144966Svkashyap			/*
657144966Svkashyap			 * If none of the above errors occurred, simply
658144966Svkashyap			 * mark completion error.
659144966Svkashyap			 */
660144966Svkashyap			if (ccb->ccb_h.status == 0)
661144966Svkashyap				ccb->ccb_h.status = CAM_REQ_CMP_ERR;
662144966Svkashyap
663144966Svkashyap			if (req_pkt->status & TW_CL_ERR_REQ_AUTO_SENSE_VALID) {
664144966Svkashyap				ccb->csio.sense_len = scsi_req->sense_len;
665144966Svkashyap				ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
666144966Svkashyap			}
667144966Svkashyap		}
668144966Svkashyap
669144966Svkashyap		ccb->csio.scsi_status = scsi_req->scsi_status;
670144966Svkashyap	}
671144966Svkashyap
672144966Svkashyap	ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
673172496Sscottl	mtx_lock(sc->sim_lock);
674144966Svkashyap	xpt_done(ccb);
675172496Sscottl	mtx_unlock(sc->sim_lock);
676144966Svkashyap	if (! req->error_code)
677144966Svkashyap		 /* twa_action will free the request otherwise */
678144966Svkashyap		tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q);
679144966Svkashyap}
680144966Svkashyap
681