tw_osl_cam.c revision 163816
1144966Svkashyap/*
2169400Sscottl * Copyright (c) 2004-05 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 163816 2006-10-31 05:53:29Z mjacob $
28144966Svkashyap */
29144966Svkashyap
30144966Svkashyap/*
31144966Svkashyap * AMCC'S 3ware driver for 9000 series storage controllers.
32144966Svkashyap *
33144966Svkashyap * Author: Vinod Kashyap
34169400Sscottl */
35172496Sscottl
36144966Svkashyap
37144966Svkashyap/*
38144966Svkashyap * FreeBSD CAM related functions.
39144966Svkashyap */
40144966Svkashyap
41144966Svkashyap
42144966Svkashyap#include <dev/twa/tw_osl_includes.h>
43144966Svkashyap
44149968Sobrien#include <cam/cam.h>
45144966Svkashyap#include <cam/cam_ccb.h>
46144966Svkashyap#include <cam/cam_sim.h>
47144966Svkashyap#include <cam/cam_xpt_sim.h>
48144966Svkashyap#include <cam/cam_debug.h>
49144966Svkashyap#include <cam/cam_periph.h>
50144966Svkashyap
51144966Svkashyap#include <cam/scsi/scsi_all.h>
52144966Svkashyap#include <cam/scsi/scsi_message.h>
53144966Svkashyap
54144966Svkashyapstatic TW_VOID	twa_action(struct cam_sim *sim, union ccb *ccb);
55144966Svkashyapstatic TW_VOID	twa_poll(struct cam_sim *sim);
56144966Svkashyapstatic TW_VOID	twa_async(TW_VOID *callback_arg, TW_UINT32 code,
57144966Svkashyap	struct cam_path *path, TW_VOID *arg);
58144966Svkashyapstatic TW_VOID	twa_timeout(TW_VOID *arg);
59144966Svkashyapstatic TW_VOID	twa_bus_scan_cb(struct cam_periph *periph, union ccb *ccb);
60144966Svkashyap
61144966Svkashyapstatic TW_INT32	tw_osli_execute_scsi(struct tw_osli_req_context *req,
62144966Svkashyap	union ccb *ccb);
63144966Svkashyap
64144966Svkashyap
65144966Svkashyap
66144966Svkashyap/*
67144966Svkashyap * Function name:	tw_osli_cam_attach
68144966Svkashyap * Description:		Attaches the driver to CAM.
69144966Svkashyap *
70144966Svkashyap * Input:		sc	-- ptr to OSL internal ctlr context
71144966Svkashyap * Output:		None
72144966Svkashyap * Return value:	0	-- success
73144966Svkashyap *			non-zero-- failure
74144966Svkashyap */
75144966SvkashyapTW_INT32
76144966Svkashyaptw_osli_cam_attach(struct twa_softc *sc)
77144966Svkashyap{
78144966Svkashyap	struct cam_devq		*devq;
79144966Svkashyap	struct ccb_setasync	csa;
80144966Svkashyap	TW_INT32		error;
81144966Svkashyap
82144966Svkashyap	tw_osli_dbg_dprintf(3, sc, "entered");
83212008Sdelphij
84144966Svkashyap	/*
85144966Svkashyap	 * Create the device queue for our SIM.
86144966Svkashyap	 */
87144966Svkashyap	if ((devq = cam_simq_alloc(TW_OSLI_MAX_NUM_IOS)) == NULL) {
88144966Svkashyap		tw_osli_printf(sc, "error = %d",
89144966Svkashyap			TW_CL_SEVERITY_ERROR_STRING,
90144966Svkashyap			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
91144966Svkashyap			0x2100,
92144966Svkashyap			"Failed to create SIM device queue",
93144966Svkashyap			ENOMEM);
94208969Sdelphij		return(ENOMEM);
95144966Svkashyap	}
96208969Sdelphij
97208969Sdelphij	/*
98144966Svkashyap	 * Create a SIM entry.  Though we can support TW_OSLI_MAX_NUM_IOS
99144966Svkashyap	 * simultaneous requests, we claim to be able to handle only
100144966Svkashyap	 * (TW_OSLI_MAX_NUM_IOS - 1), so that we always have a request
101172496Sscottl	 * packet available to service ioctls.
102208969Sdelphij	 */
103144966Svkashyap	tw_osli_dbg_dprintf(3, sc, "Calling cam_sim_alloc");
104144966Svkashyap	sc->sim = cam_sim_alloc(twa_action, twa_poll, "twa", sc,
105144966Svkashyap			device_get_unit(sc->bus_dev),
106144966Svkashyap			TW_OSLI_MAX_NUM_IOS - 1, 1, devq);
107144966Svkashyap	if (sc->sim == NULL) {
108144966Svkashyap		cam_simq_free(devq);
109144966Svkashyap		tw_osli_printf(sc, "error = %d",
110144966Svkashyap			TW_CL_SEVERITY_ERROR_STRING,
111144966Svkashyap			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
112144966Svkashyap			0x2101,
113144966Svkashyap			"Failed to create a SIM entry",
114144966Svkashyap			ENOMEM);
115144966Svkashyap		return(ENOMEM);
116144966Svkashyap	}
117144966Svkashyap
118172496Sscottl	/*
119170872Sscottl	 * Register the bus.
120144966Svkashyap	 */
121144966Svkashyap	tw_osli_dbg_dprintf(3, sc, "Calling xpt_bus_register");
122144966Svkashyap	mtx_lock(&Giant);
123144966Svkashyap	if (xpt_bus_register(sc->sim, 0) != CAM_SUCCESS) {
124144966Svkashyap		cam_sim_free(sc->sim, TRUE);
125144966Svkashyap		sc->sim = NULL; /* so cam_detach will not try to free it */
126144966Svkashyap		tw_osli_printf(sc, "error = %d",
127144966Svkashyap			TW_CL_SEVERITY_ERROR_STRING,
128172496Sscottl			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
129144966Svkashyap			0x2102,
130144966Svkashyap			"Failed to register the bus",
131144966Svkashyap			ENXIO);
132144966Svkashyap		return(ENXIO);
133144966Svkashyap	}
134144966Svkashyap
135144966Svkashyap	tw_osli_dbg_dprintf(3, sc, "Calling xpt_create_path");
136144966Svkashyap	if (xpt_create_path(&sc->path, NULL,
137144966Svkashyap				cam_sim_path(sc->sim),
138144966Svkashyap				CAM_TARGET_WILDCARD,
139144966Svkashyap				CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
140144966Svkashyap		xpt_bus_deregister(cam_sim_path (sc->sim));
141144966Svkashyap		/* Passing TRUE to cam_sim_free will free the devq as well. */
142144966Svkashyap		cam_sim_free(sc->sim, TRUE);
143144966Svkashyap		tw_osli_printf(sc, "error = %d",
144144966Svkashyap			TW_CL_SEVERITY_ERROR_STRING,
145144966Svkashyap			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
146172496Sscottl			0x2103,
147144966Svkashyap			"Failed to create path",
148144966Svkashyap			ENXIO);
149172496Sscottl		return(ENXIO);
150144966Svkashyap	}
151144966Svkashyap
152144966Svkashyap	tw_osli_dbg_dprintf(3, sc, "Calling xpt_setup_ccb");
153144966Svkashyap	xpt_setup_ccb(&csa.ccb_h, sc->path, 5);
154144966Svkashyap	csa.ccb_h.func_code = XPT_SASYNC_CB;
155144966Svkashyap	csa.event_enable = AC_FOUND_DEVICE | AC_LOST_DEVICE;
156144966Svkashyap	csa.callback = twa_async;
157144966Svkashyap	csa.callback_arg = sc;
158144966Svkashyap	xpt_action((union ccb *)&csa);
159144966Svkashyap	mtx_unlock(&Giant);
160144966Svkashyap
161144966Svkashyap	tw_osli_dbg_dprintf(3, sc, "Calling tw_osli_request_bus_scan");
162144966Svkashyap	/*
163144966Svkashyap	 * Request a bus scan, so that CAM gets to know of
164144966Svkashyap	 * the logical units that we control.
165144966Svkashyap	 */
166144966Svkashyap	if ((error = tw_osli_request_bus_scan(sc)))
167144966Svkashyap		tw_osli_printf(sc, "error = %d",
168144966Svkashyap			TW_CL_SEVERITY_ERROR_STRING,
169144966Svkashyap			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
170172496Sscottl			0x2104,
171172496Sscottl			"Bus scan request to CAM failed",
172144966Svkashyap			error);
173144966Svkashyap
174144966Svkashyap	tw_osli_dbg_dprintf(3, sc, "exiting");
175144966Svkashyap	return(0);
176144966Svkashyap}
177144966Svkashyap
178144966Svkashyap
179172496Sscottl
180172496Sscottl/*
181144966Svkashyap * Function name:	tw_osli_cam_detach
182144966Svkashyap * Description:		Detaches the driver from CAM.
183144966Svkashyap *
184144966Svkashyap * Input:		sc	-- ptr to OSL internal ctlr context
185144966Svkashyap * Output:		None
186144966Svkashyap * Return value:	None
187144966Svkashyap */
188144966SvkashyapTW_VOID
189144966Svkashyaptw_osli_cam_detach(struct twa_softc *sc)
190144966Svkashyap{
191144966Svkashyap	tw_osli_dbg_dprintf(3, sc, "entered");
192144966Svkashyap
193144966Svkashyap	mtx_lock(&Giant);
194144966Svkashyap	if (sc->path)
195144966Svkashyap		xpt_free_path(sc->path);
196144966Svkashyap	if (sc->sim) {
197144966Svkashyap		xpt_bus_deregister(cam_sim_path(sc->sim));
198144966Svkashyap		/* Passing TRUE to cam_sim_free will free the devq as well. */
199144966Svkashyap		cam_sim_free(sc->sim, TRUE);
200144966Svkashyap	}
201144966Svkashyap	mtx_unlock(&Giant);
202144966Svkashyap}
203144966Svkashyap
204144966Svkashyap
205144966Svkashyap
206144966Svkashyap/*
207144966Svkashyap * Function name:	tw_osli_execute_scsi
208144966Svkashyap * Description:		Build a fw cmd, based on a CAM style ccb, and
209144966Svkashyap *			send it down.
210144966Svkashyap *
211144966Svkashyap * Input:		req	-- ptr to OSL internal request context
212144966Svkashyap *			ccb	-- ptr to CAM style ccb
213144966Svkashyap * Output:		None
214144966Svkashyap * Return value:	0	-- success
215144966Svkashyap *			non-zero-- failure
216144966Svkashyap */
217144966SvkashyapTW_INT32
218144966Svkashyaptw_osli_execute_scsi(struct tw_osli_req_context *req, union ccb *ccb)
219144966Svkashyap{
220144966Svkashyap	struct twa_softc		*sc = req->ctlr;
221144966Svkashyap	struct tw_cl_req_packet		*req_pkt;
222144966Svkashyap	struct tw_cl_scsi_req_packet	*scsi_req;
223144966Svkashyap	struct ccb_hdr			*ccb_h = &(ccb->ccb_h);
224144966Svkashyap	struct ccb_scsiio		*csio = &(ccb->csio);
225144966Svkashyap	TW_INT32			error;
226144966Svkashyap
227144966Svkashyap	tw_osli_dbg_dprintf(10, sc, "SCSI I/O request 0x%x",
228144966Svkashyap		csio->cdb_io.cdb_bytes[0]);
229144966Svkashyap
230208969Sdelphij	if (ccb_h->target_id >= TW_CL_MAX_NUM_UNITS) {
231144966Svkashyap		tw_osli_dbg_dprintf(3, sc, "Invalid target. PTL = %x %x %x",
232144966Svkashyap			ccb_h->path_id, ccb_h->target_id, ccb_h->target_lun);
233144966Svkashyap		ccb_h->status |= CAM_TID_INVALID;
234144966Svkashyap		xpt_done(ccb);
235144966Svkashyap		return(1);
236144966Svkashyap	}
237144966Svkashyap	if (ccb_h->target_lun >= TW_CL_MAX_NUM_LUNS) {
238144966Svkashyap		tw_osli_dbg_dprintf(3, sc, "Invalid lun. PTL = %x %x %x",
239144966Svkashyap			ccb_h->path_id, ccb_h->target_id, ccb_h->target_lun);
240144966Svkashyap		ccb_h->status |= CAM_LUN_INVALID;
241144966Svkashyap		xpt_done(ccb);
242144966Svkashyap		return(1);
243144966Svkashyap	}
244144966Svkashyap
245144966Svkashyap	if(ccb_h->flags & CAM_CDB_PHYS) {
246144966Svkashyap		tw_osli_printf(sc, "",
247144966Svkashyap			TW_CL_SEVERITY_ERROR_STRING,
248144966Svkashyap			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
249144966Svkashyap			0x2105,
250144966Svkashyap			"Physical CDB address!");
251144966Svkashyap		ccb_h->status = CAM_REQ_CMP_ERR;
252144966Svkashyap		xpt_done(ccb);
253144966Svkashyap		return(1);
254144966Svkashyap	}
255144966Svkashyap
256144966Svkashyap	/*
257144966Svkashyap	 * We are going to work on this request.  Mark it as enqueued (though
258144966Svkashyap	 * we don't actually queue it...)
259144966Svkashyap	 */
260144966Svkashyap	ccb_h->status |= CAM_SIM_QUEUED;
261144966Svkashyap
262144966Svkashyap	if((ccb_h->flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
263144966Svkashyap		if(ccb_h->flags & CAM_DIR_IN)
264246713Skib			req->flags |= TW_OSLI_REQ_FLAGS_DATA_IN;
265246713Skib		else
266144966Svkashyap			req->flags |= TW_OSLI_REQ_FLAGS_DATA_OUT;
267144966Svkashyap	}
268246713Skib
269246713Skib	/* Build the CL understood request packet for SCSI cmds. */
270246713Skib	req_pkt = &req->req_pkt;
271246713Skib	req_pkt->status = 0;
272144966Svkashyap	req_pkt->tw_osl_callback = tw_osl_complete_io;
273144966Svkashyap	scsi_req = &(req_pkt->gen_req_pkt.scsi_req);
274144966Svkashyap	scsi_req->unit = ccb_h->target_id;
275144966Svkashyap	scsi_req->lun = ccb_h->target_lun;
276246713Skib	scsi_req->sense_len = 0;
277246713Skib	scsi_req->sense_data = (TW_UINT8 *)(&csio->sense_data);
278246713Skib	scsi_req->scsi_status = 0;
279212008Sdelphij	if(ccb_h->flags & CAM_CDB_POINTER)
280212008Sdelphij		scsi_req->cdb = csio->cdb_io.cdb_ptr;
281144966Svkashyap	else
282144966Svkashyap		scsi_req->cdb = csio->cdb_io.cdb_bytes;
283144966Svkashyap	scsi_req->cdb_len = csio->cdb_len;
284144966Svkashyap
285144966Svkashyap	if (!(ccb_h->flags & CAM_DATA_PHYS)) {
286212008Sdelphij		/* Virtual data addresses.  Need to convert them... */
287212008Sdelphij		tw_osli_dbg_dprintf(3, sc,
288212008Sdelphij			"XPT_SCSI_IO: Single virtual address!");
289212008Sdelphij		if (!(ccb_h->flags & CAM_SCATTER_VALID)) {
290212008Sdelphij			if (csio->dxfer_len > TW_CL_MAX_IO_SIZE) {
291212008Sdelphij				tw_osli_printf(sc, "size = %d",
292144966Svkashyap					TW_CL_SEVERITY_ERROR_STRING,
293144966Svkashyap					TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
294144966Svkashyap					0x2106,
295144966Svkashyap					"I/O size too big",
296144966Svkashyap					csio->dxfer_len);
297144966Svkashyap				ccb_h->status = CAM_REQ_TOO_BIG;
298144966Svkashyap				xpt_done(ccb);
299144966Svkashyap				return(1);
300144966Svkashyap			}
301144966Svkashyap
302144966Svkashyap			if ((req->length = csio->dxfer_len)) {
303144966Svkashyap				req->data = csio->data_ptr;
304144966Svkashyap				scsi_req->sgl_entries = 1;
305144966Svkashyap			}
306144966Svkashyap		} else {
307144966Svkashyap			tw_osli_printf(sc, "",
308144966Svkashyap				TW_CL_SEVERITY_ERROR_STRING,
309144966Svkashyap				TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
310144966Svkashyap				0x2107,
311144966Svkashyap				"XPT_SCSI_IO: Got SGList");
312144966Svkashyap			ccb_h->status = CAM_REQ_CMP_ERR;
313144966Svkashyap			xpt_done(ccb);
314144966Svkashyap			return(1);
315144966Svkashyap		}
316144966Svkashyap	} else {
317208969Sdelphij		/* Data addresses are physical. */
318208969Sdelphij		tw_osli_printf(sc, "",
319208969Sdelphij			TW_CL_SEVERITY_ERROR_STRING,
320144966Svkashyap			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
321144966Svkashyap			0x2108,
322144966Svkashyap			"XPT_SCSI_IO: Physical data addresses");
323144966Svkashyap		ccb_h->status = CAM_REQ_CMP_ERR;
324212008Sdelphij		ccb_h->status |= CAM_RELEASE_SIMQ;
325144966Svkashyap		ccb_h->status &= ~CAM_SIM_QUEUED;
326144966Svkashyap		xpt_done(ccb);
327144966Svkashyap		return(1);
328144966Svkashyap	}
329212008Sdelphij
330212008Sdelphij	ccb_h->timeout_ch = timeout(twa_timeout, req,
331212008Sdelphij		(ccb_h->timeout * hz) / 1000);
332212008Sdelphij	/*
333212008Sdelphij	 * twa_map_load_data_callback will fill in the SGL,
334212008Sdelphij	 * and submit the I/O.
335212008Sdelphij	 */
336212008Sdelphij	error = tw_osli_map_request(req);
337212008Sdelphij	return(error);
338144966Svkashyap}
339208969Sdelphij
340144966Svkashyap
341144966Svkashyap
342144966Svkashyap/*
343144966Svkashyap * Function name:	twa_action
344144966Svkashyap * Description:		Driver entry point for CAM's use.
345144966Svkashyap *
346144966Svkashyap * Input:		sim	-- sim corresponding to the ctlr
347144966Svkashyap *			ccb	-- ptr to CAM request
348144966Svkashyap * Output:		None
349144966Svkashyap * Return value:	None
350144966Svkashyap */
351144966SvkashyapTW_VOID
352144966Svkashyaptwa_action(struct cam_sim *sim, union ccb *ccb)
353212008Sdelphij{
354144966Svkashyap	struct twa_softc	*sc = (struct twa_softc *)cam_sim_softc(sim);
355144966Svkashyap	struct ccb_hdr		*ccb_h = &(ccb->ccb_h);
356144966Svkashyap
357144966Svkashyap	switch (ccb_h->func_code) {
358144966Svkashyap	case XPT_SCSI_IO:	/* SCSI I/O */
359212008Sdelphij	{
360212008Sdelphij		struct tw_osli_req_context	*req;
361144966Svkashyap
362144966Svkashyap		if ((sc->state & TW_OSLI_CTLR_STATE_SIMQ_FROZEN) ||
363144966Svkashyap				((req = tw_osli_get_request(sc)) == NULL)) {
364144966Svkashyap			tw_osli_dbg_dprintf(2, sc,
365144966Svkashyap				"simq frozen/Cannot get request pkt.");
366144966Svkashyap			/*
367144966Svkashyap			 * Freeze the simq to maintain ccb ordering.  The next
368144966Svkashyap			 * ccb that gets completed will unfreeze the simq.
369144966Svkashyap			 */
370144966Svkashyap			tw_osli_disallow_new_requests(sc);
371144966Svkashyap			ccb_h->status |= CAM_REQUEUE_REQ;
372144966Svkashyap			xpt_done(ccb);
373144966Svkashyap			break;
374144966Svkashyap		}
375144966Svkashyap		req->req_handle.osl_req_ctxt = req;
376144966Svkashyap		req->orig_req = ccb;
377144966Svkashyap		if (tw_osli_execute_scsi(req, ccb))
378163816Smjacob			tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q);
379163816Smjacob		break;
380163816Smjacob	}
381163816Smjacob
382144966Svkashyap	case XPT_ABORT:
383163816Smjacob		tw_osli_dbg_dprintf(2, sc, "Abort request.");
384163816Smjacob		ccb_h->status = CAM_UA_ABORT;
385163816Smjacob		xpt_done(ccb);
386163816Smjacob		break;
387163816Smjacob
388163816Smjacob	case XPT_RESET_BUS:
389163816Smjacob		tw_cl_create_event(&(sc->ctlr_handle), TW_CL_TRUE,
390163816Smjacob			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
391163816Smjacob			0x2108, 0x3, TW_CL_SEVERITY_INFO_STRING,
392163816Smjacob			"Received Reset Bus request from CAM",
393144966Svkashyap			" ");
394144966Svkashyap
395144966Svkashyap		if (tw_cl_reset_ctlr(&sc->ctlr_handle)) {
396144966Svkashyap			tw_cl_create_event(&(sc->ctlr_handle), TW_CL_TRUE,
397144966Svkashyap				TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
398144966Svkashyap				0x2109, 0x1, TW_CL_SEVERITY_ERROR_STRING,
399144966Svkashyap				"Failed to reset bus",
400144966Svkashyap				" ");
401144966Svkashyap			ccb_h->status = CAM_REQ_CMP_ERR;
402144966Svkashyap		}
403144966Svkashyap		else
404144966Svkashyap			ccb_h->status = CAM_REQ_CMP;
405144966Svkashyap
406144966Svkashyap		xpt_done(ccb);
407144966Svkashyap		break;
408144966Svkashyap
409144966Svkashyap	case XPT_SET_TRAN_SETTINGS:
410144966Svkashyap		tw_osli_dbg_dprintf(3, sc, "XPT_SET_TRAN_SETTINGS");
411144966Svkashyap
412144966Svkashyap		/*
413144966Svkashyap		 * This command is not supported, since it's very specific
414144966Svkashyap		 * to SCSI, and we are doing ATA.
415144966Svkashyap		 */
416144966Svkashyap  		ccb_h->status = CAM_FUNC_NOTAVAIL;
417144966Svkashyap  		xpt_done(ccb);
418144966Svkashyap  		break;
419152213Svkashyap
420144966Svkashyap	case XPT_GET_TRAN_SETTINGS:
421144966Svkashyap	{
422144966Svkashyap		struct ccb_trans_settings	*cts = &ccb->cts;
423144966Svkashyap#ifdef	CAM_NEW_TRAN_CODE
424163816Smjacob		struct ccb_trans_settings_scsi *scsi =
425163816Smjacob		    &cts->proto_specific.scsi;
426163816Smjacob		struct ccb_trans_settings_spi *spi =
427163816Smjacob		    &cts->xport_specific.spi;
428212008Sdelphij
429144966Svkashyap		cts->protocol = PROTO_SCSI;
430144966Svkashyap		cts->protocol_version = SCSI_REV_2;
431144966Svkashyap		cts->transport = XPORT_SPI;
432144966Svkashyap		cts->transport_version = 2;
433144966Svkashyap
434144966Svkashyap		spi->valid = CTS_SPI_VALID_DISC;
435144966Svkashyap		spi->flags = CTS_SPI_FLAGS_DISC_ENB;
436144966Svkashyap		scsi->valid = CTS_SCSI_VALID_TQ;
437144966Svkashyap		scsi->flags = CTS_SCSI_FLAGS_TAG_ENB;
438144966Svkashyap#else
439144966Svkashyap		cts->valid = (CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID);
440144966Svkashyap		cts->flags &= ~(CCB_TRANS_DISC_ENB | CCB_TRANS_TAG_ENB);
441144966Svkashyap#endif
442144966Svkashyap		tw_osli_dbg_dprintf(3, sc, "XPT_GET_TRAN_SETTINGS");
443144966Svkashyap		ccb_h->status = CAM_REQ_CMP;
444144966Svkashyap		xpt_done(ccb);
445144966Svkashyap		break;
446144966Svkashyap	}
447144966Svkashyap
448144966Svkashyap	case XPT_CALC_GEOMETRY:
449144966Svkashyap		tw_osli_dbg_dprintf(3, sc, "XPT_CALC_GEOMETRY");
450144966Svkashyap		cam_calc_geometry(&ccb->ccg, 1/* extended */);
451144966Svkashyap		xpt_done(ccb);
452144966Svkashyap		break;
453144966Svkashyap
454144966Svkashyap	case XPT_PATH_INQ:    /* Path inquiry -- get twa properties */
455144966Svkashyap	{
456144966Svkashyap		struct ccb_pathinq	*path_inq = &ccb->cpi;
457144966Svkashyap
458144966Svkashyap		tw_osli_dbg_dprintf(3, sc, "XPT_PATH_INQ request");
459145688Svkashyap
460144966Svkashyap		path_inq->version_num = 1;
461144966Svkashyap		path_inq->hba_inquiry = 0;
462144966Svkashyap		path_inq->target_sprt = 0;
463144966Svkashyap		path_inq->hba_misc = 0;
464144966Svkashyap		path_inq->hba_eng_cnt = 0;
465144966Svkashyap		path_inq->max_target = TW_CL_MAX_NUM_UNITS;
466144966Svkashyap		path_inq->max_lun = TW_CL_MAX_NUM_LUNS - 1;
467144966Svkashyap		path_inq->unit_number = cam_sim_unit(sim);
468144966Svkashyap		path_inq->bus_id = cam_sim_bus(sim);
469144966Svkashyap		path_inq->initiator_id = TW_CL_MAX_NUM_UNITS;
470144966Svkashyap		path_inq->base_transfer_speed = 100000;
471144966Svkashyap		strncpy(path_inq->sim_vid, "FreeBSD", SIM_IDLEN);
472144966Svkashyap		strncpy(path_inq->hba_vid, "3ware", HBA_IDLEN);
473144966Svkashyap		strncpy(path_inq->dev_name, cam_sim_name(sim), DEV_IDLEN);
474144966Svkashyap#ifdef	CAM_NEW_TRAN_CODE
475144966Svkashyap                path_inq->transport = XPORT_SPI;
476144966Svkashyap                path_inq->transport_version = 2;
477144966Svkashyap                path_inq->protocol = PROTO_SCSI;
478144966Svkashyap                path_inq->protocol_version = SCSI_REV_2;
479144966Svkashyap#endif
480144966Svkashyap		ccb_h->status = CAM_REQ_CMP;
481152213Svkashyap		xpt_done(ccb);
482152213Svkashyap		break;
483152213Svkashyap	}
484203108Smav
485144966Svkashyap	default:
486172496Sscottl		tw_osli_dbg_dprintf(3, sc, "func_code = %x", ccb_h->func_code);
487203108Smav		ccb_h->status = CAM_REQ_INVALID;
488203108Smav		xpt_done(ccb);
489203108Smav		break;
490172496Sscottl	}
491144966Svkashyap}
492169400Sscottl
493144966Svkashyap
494203108Smav
495172496Sscottl/*
496144966Svkashyap * Function name:	twa_poll
497144966Svkashyap * Description:		Driver entry point called when interrupts are not
498144966Svkashyap *			available.
499144966Svkashyap *
500144966Svkashyap * Input:		sim	-- sim corresponding to the controller
501144966Svkashyap * Output:		None
502144966Svkashyap * Return value:	None
503144966Svkashyap */
504144966SvkashyapTW_VOID
505144966Svkashyaptwa_poll(struct cam_sim *sim)
506144966Svkashyap{
507208969Sdelphij	struct twa_softc *sc = (struct twa_softc *)(cam_sim_softc(sim));
508144966Svkashyap
509144966Svkashyap	tw_osli_dbg_dprintf(3, sc, "entering; sc = %p", sc);
510144966Svkashyap	/*
511144966Svkashyap	 * It's been observed that twa_poll can get called (from
512208969Sdelphij	 * dashutdown --> xpt_polled_action) even when interrupts are
513208969Sdelphij	 * active, in which case, the ISR might clear the interrupt,
514144966Svkashyap	 * leaving the call to tw_cl_interrupt below, no way of determining
515208969Sdelphij	 * that the response from firmware is ready, resulting in
516208969Sdelphij	 * tw_cl_deferred_interrupt never getting called.  To cover this case,
517208969Sdelphij	 * we will make the call to tw_cl_deferred_interrupt not dependent
518208969Sdelphij	 * on the return value from tw_cl_interrupt.
519208969Sdelphij	 */
520172496Sscottl	tw_cl_interrupt(&(sc->ctlr_handle));
521208969Sdelphij	tw_cl_deferred_interrupt(&(sc->ctlr_handle));
522172496Sscottl	tw_osli_dbg_dprintf(3, sc, "exiting; sc = %p", sc);
523144966Svkashyap}
524144966Svkashyap
525144966Svkashyap
526144966Svkashyap
527144966Svkashyap/*
528212008Sdelphij * Function name:	twa_async
529212008Sdelphij * Description:		Driver entry point for CAM to notify driver of special
530152213Svkashyap *			events.  We don't use this for now.
531212008Sdelphij *
532152213Svkashyap * Input:		callback_arg	-- ptr to per ctlr structure
533152213Svkashyap *			code		-- code associated with the event
534152213Svkashyap *			path		-- cam path
535152213Svkashyap *			arg		--
536212008Sdelphij * Output:		None
537152213Svkashyap * Return value:	0	-- success
538212008Sdelphij *			non-zero-- failure
539212008Sdelphij */
540212008SdelphijTW_VOID
541212008Sdelphijtwa_async(TW_VOID *callback_arg, TW_UINT32 code,
542212008Sdelphij	struct cam_path *path, TW_VOID *arg)
543152213Svkashyap{
544152213Svkashyap#ifdef TW_OSL_DEBUG
545152213Svkashyap	struct twa_softc *sc = (struct twa_softc *)callback_arg;
546152213Svkashyap#endif /* TW_OSL_DEBUG */
547152213Svkashyap
548212008Sdelphij	tw_osli_dbg_dprintf(3, sc, "sc = %p, code = %x, path = %p, arg = %p",
549212008Sdelphij		sc, code, path, arg);
550212008Sdelphij}
551212008Sdelphij
552212008Sdelphij
553212008Sdelphij
554212008Sdelphij/*
555212008Sdelphij * Function name:	twa_timeout
556212008Sdelphij * Description:		Driver entry point for being alerted on a request
557212008Sdelphij *			timing out.
558212008Sdelphij *
559212008Sdelphij * Input:		arg	-- ptr to timed out request
560212008Sdelphij * Output:		None
561212008Sdelphij * Return value:	None
562212008Sdelphij */
563212008Sdelphijstatic TW_VOID
564212008Sdelphijtwa_timeout(TW_VOID *arg)
565212008Sdelphij{
566144966Svkashyap	struct tw_osli_req_context	*req =
567144966Svkashyap		(struct tw_osli_req_context *)arg;
568144966Svkashyap
569144966Svkashyap	tw_cl_create_event(&(req->ctlr->ctlr_handle), TW_CL_TRUE,
570144966Svkashyap		TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
571144966Svkashyap		0x210B, 0x1, TW_CL_SEVERITY_ERROR_STRING,
572144966Svkashyap		"Request timed out!",
573144966Svkashyap		"request = %p", req);
574144966Svkashyap	tw_cl_reset_ctlr(&(req->ctlr->ctlr_handle));
575144966Svkashyap}
576144966Svkashyap
577144966Svkashyap
578144966Svkashyap
579144966Svkashyap/*
580144966Svkashyap * Function name:	tw_osli_request_bus_scan
581144966Svkashyap * Description:		Requests CAM for a scan of the bus.
582144966Svkashyap *
583144966Svkashyap * Input:		sc	-- ptr to per ctlr structure
584144966Svkashyap * Output:		None
585144966Svkashyap * Return value:	0	-- success
586144966Svkashyap *			non-zero-- failure
587144966Svkashyap */
588144966SvkashyapTW_INT32
589144966Svkashyaptw_osli_request_bus_scan(struct twa_softc *sc)
590144966Svkashyap{
591144966Svkashyap	struct cam_path	*path;
592144966Svkashyap	union ccb	*ccb;
593144966Svkashyap
594144966Svkashyap	tw_osli_dbg_dprintf(3, sc, "entering");
595144966Svkashyap
596144966Svkashyap	/* If we get here before sc->sim is initialized, return an error. */
597144966Svkashyap	if (!(sc->sim))
598144966Svkashyap		return(ENXIO);
599144966Svkashyap	if ((ccb = malloc(sizeof(union ccb), M_TEMP, M_WAITOK)) == NULL)
600144966Svkashyap		return(ENOMEM);
601144966Svkashyap	bzero(ccb, sizeof(union ccb));
602144966Svkashyap	mtx_lock(&Giant);
603144966Svkashyap	if (xpt_create_path(&path, xpt_periph, cam_sim_path(sc->sim),
604144966Svkashyap		CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP)
605144966Svkashyap		return(EIO);
606144966Svkashyap
607144966Svkashyap	xpt_setup_ccb(&ccb->ccb_h, path, 5);
608144966Svkashyap	ccb->ccb_h.func_code = XPT_SCAN_BUS;
609144966Svkashyap	ccb->ccb_h.cbfcnp = twa_bus_scan_cb;
610144966Svkashyap	ccb->crcn.flags = CAM_FLAG_NONE;
611144966Svkashyap	xpt_action(ccb);
612144966Svkashyap	mtx_unlock(&Giant);
613144966Svkashyap	return(0);
614144966Svkashyap}
615144966Svkashyap
616144966Svkashyap
617144966Svkashyap
618144966Svkashyap/*
619144966Svkashyap * Function name:	twa_bus_scan_cb
620144966Svkashyap * Description:		Callback from CAM on a bus scan request.
621144966Svkashyap *
622144966Svkashyap * Input:		periph	-- we don't use this
623144966Svkashyap *			ccb	-- bus scan request ccb that we sent to CAM
624144966Svkashyap * Output:		None
625144966Svkashyap * Return value:	None
626144966Svkashyap */
627144966Svkashyapstatic TW_VOID
628212008Sdelphijtwa_bus_scan_cb(struct cam_periph *periph, union ccb *ccb)
629144966Svkashyap{
630144966Svkashyap	tw_osli_dbg_printf(3, "entering");
631144966Svkashyap
632144966Svkashyap	if (ccb->ccb_h.status != CAM_REQ_CMP)
633152213Svkashyap		printf("cam_scan_callback: failure status = %x\n",
634208969Sdelphij			ccb->ccb_h.status);
635208969Sdelphij	else
636144966Svkashyap		tw_osli_dbg_printf(3, "success");
637144966Svkashyap
638144966Svkashyap	xpt_free_path(ccb->ccb_h.path);
639144966Svkashyap	free(ccb, M_TEMP);
640144966Svkashyap}
641144966Svkashyap
642144966Svkashyap
643144966Svkashyap
644144966Svkashyap/*
645144966Svkashyap * Function name:	tw_osli_allow_new_requests
646144966Svkashyap * Description:		Sets the appropriate status bits in a ccb such that,
647144966Svkashyap *			when the ccb is completed by a call to xpt_done,
648144966Svkashyap *			CAM knows that it's ok to unfreeze the flow of new
649237460Smav *			requests to this controller, if the flow is frozen.
650144966Svkashyap *
651237460Smav * Input:		sc	-- ptr to OSL internal ctlr context
652144966Svkashyap *			ccb	-- ptr to CAM request
653144966Svkashyap * Output:		None
654144966Svkashyap * Return value:	None
655212008Sdelphij */
656144966SvkashyapTW_VOID
657144966Svkashyaptw_osli_allow_new_requests(struct twa_softc *sc, TW_VOID *ccb)
658144966Svkashyap{
659144966Svkashyap	((union ccb *)(ccb))->ccb_h.status |= CAM_RELEASE_SIMQ;
660144966Svkashyap	sc->state &= ~TW_OSLI_CTLR_STATE_SIMQ_FROZEN;
661144966Svkashyap}
662144966Svkashyap
663144966Svkashyap
664144966Svkashyap
665144966Svkashyap/*
666144966Svkashyap * Function name:	tw_osli_disallow_new_requests
667144966Svkashyap * Description:		Calls the appropriate CAM function, so as to freeze
668144966Svkashyap *			the flow of new requests from CAM to this controller.
669144966Svkashyap *
670144966Svkashyap * Input:		sc	-- ptr to OSL internal ctlr context
671144966Svkashyap * Output:		None
672144966Svkashyap * Return value:	None
673172496Sscottl */
674144966SvkashyapTW_VOID
675172496Sscottltw_osli_disallow_new_requests(struct twa_softc *sc)
676144966Svkashyap{
677144966Svkashyap	mtx_lock(&Giant);
678144966Svkashyap	xpt_freeze_simq(sc->sim, 1);
679144966Svkashyap	mtx_unlock(&Giant);
680144966Svkashyap	sc->state |= TW_OSLI_CTLR_STATE_SIMQ_FROZEN;
681}
682
683
684
685/*
686 * Function name:	tw_osl_ctlr_busy
687 * Description:		CL calls this function on cmd queue full or otherwise,
688 *			when it is too busy to accept new requests.
689 *
690 * Input:		ctlr_handle	-- ptr to controller handle
691 *			req_handle	-- ptr to request handle sent by OSL.
692 * Output:		None
693 * Return value:	None
694 */
695TW_VOID
696tw_osl_ctlr_busy(struct tw_cl_ctlr_handle *ctlr_handle,
697	struct tw_cl_req_handle *req_handle)
698{
699	tw_osli_disallow_new_requests(ctlr_handle->osl_ctlr_ctxt);
700}
701
702
703
704/*
705 * Function name:	tw_osl_scan_bus
706 * Description:		CL calls this function to request for a bus scan.
707 *
708 * Input:		ctlr_handle	-- ptr to controller handle
709 * Output:		None
710 * Return value:	None
711 */
712TW_VOID
713tw_osl_scan_bus(struct tw_cl_ctlr_handle *ctlr_handle)
714{
715	struct twa_softc	*sc = ctlr_handle->osl_ctlr_ctxt;
716	TW_INT32		error;
717
718	if ((error = tw_osli_request_bus_scan(sc)))
719		tw_osli_printf(sc, "error = %d",
720			TW_CL_SEVERITY_ERROR_STRING,
721			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
722			0x2109,
723			"Bus scan request to CAM failed",
724			error);
725}
726
727
728
729/*
730 * Function name:	tw_osl_complete_io
731 * Description:		Called to complete CAM scsi requests.
732 *
733 * Input:		req_handle	-- ptr to request handle
734 * Output:		None
735 * Return value:	None
736 */
737TW_VOID
738tw_osl_complete_io(struct tw_cl_req_handle *req_handle)
739{
740	struct tw_osli_req_context	*req = req_handle->osl_req_ctxt;
741	struct tw_cl_req_packet		*req_pkt =
742		(struct tw_cl_req_packet *)(&req->req_pkt);
743	struct tw_cl_scsi_req_packet	*scsi_req;
744	struct twa_softc		*sc = req->ctlr;
745	union ccb			*ccb = (union ccb *)(req->orig_req);
746
747	tw_osli_dbg_dprintf(10, sc, "entering");
748
749	if (req->state != TW_OSLI_REQ_STATE_BUSY)
750		tw_osli_printf(sc, "request = %p, status = %d",
751			TW_CL_SEVERITY_ERROR_STRING,
752			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
753			0x210A,
754			"Unposted command completed!!",
755			req, req->state);
756
757	/*
758	 * Remove request from the busy queue.  Just mark it complete.
759	 * There's no need to move it into the complete queue as we are
760	 * going to be done with it right now.
761	 */
762	req->state = TW_OSLI_REQ_STATE_COMPLETE;
763	tw_osli_req_q_remove_item(req, TW_OSLI_BUSY_Q);
764
765	tw_osli_unmap_request(req);
766
767	untimeout(twa_timeout, req, ccb->ccb_h.timeout_ch);
768	if (req->error_code) {
769		/* This request never got submitted to the firmware. */
770		if (req->error_code == EBUSY) {
771			/*
772			 * Cmd queue is full, or the Common Layer is out of
773			 * resources.  The simq will already have been frozen
774			 * by CL's call to tw_osl_ctlr_busy, and this will
775			 * maintain ccb ordering.  The next ccb that gets
776			 * completed will unfreeze the simq.
777			 */
778			ccb->ccb_h.status |= CAM_REQUEUE_REQ;
779		}
780		else if (req->error_code == EFBIG)
781			ccb->ccb_h.status = CAM_REQ_TOO_BIG;
782		else
783			ccb->ccb_h.status = CAM_REQ_CMP_ERR;
784	} else {
785		scsi_req = &(req_pkt->gen_req_pkt.scsi_req);
786		if (req_pkt->status == TW_CL_ERR_REQ_SUCCESS)
787			ccb->ccb_h.status = CAM_REQ_CMP;
788		else {
789			if (req_pkt->status & TW_CL_ERR_REQ_INVALID_TARGET)
790				ccb->ccb_h.status |= CAM_TID_INVALID;
791			else if (req_pkt->status & TW_CL_ERR_REQ_INVALID_LUN)
792				ccb->ccb_h.status |= CAM_LUN_INVALID;
793			else if (req_pkt->status & TW_CL_ERR_REQ_SCSI_ERROR)
794				ccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
795			else if (req_pkt->status & TW_CL_ERR_REQ_BUS_RESET)
796				ccb->ccb_h.status |= CAM_SCSI_BUS_RESET;
797			/*
798			 * If none of the above errors occurred, simply
799			 * mark completion error.
800			 */
801			if (ccb->ccb_h.status == 0)
802				ccb->ccb_h.status = CAM_REQ_CMP_ERR;
803
804			if (req_pkt->status & TW_CL_ERR_REQ_AUTO_SENSE_VALID) {
805				ccb->csio.sense_len = scsi_req->sense_len;
806				ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
807			}
808		}
809
810		ccb->csio.scsi_status = scsi_req->scsi_status;
811		/* If simq is frozen, unfreeze it. */
812		if (sc->state & TW_OSLI_CTLR_STATE_SIMQ_FROZEN)
813			tw_osli_allow_new_requests(sc, (TW_VOID *)ccb);
814	}
815
816	ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
817	xpt_done(ccb);
818	if (! req->error_code)
819		 /* twa_action will free the request otherwise */
820		tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q);
821}
822
823