tw_osl_cam.c revision 152213
1144966Svkashyap/*
2144966Svkashyap * 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 152213 2005-11-08 22:51:43Z vkashyap $
28144966Svkashyap */
29144966Svkashyap
30144966Svkashyap/*
31144966Svkashyap * AMCC'S 3ware driver for 9000 series storage controllers.
32144966Svkashyap *
33144966Svkashyap * Author: Vinod Kashyap
34144966Svkashyap */
35144966Svkashyap
36144966Svkashyap
37144966Svkashyap/*
38144966Svkashyap * FreeBSD CAM related functions.
39144966Svkashyap */
40144966Svkashyap
41144966Svkashyap
42149968Sobrien#include <dev/twa/tw_osl_includes.h>
43144966Svkashyap
44144966Svkashyap#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_xpt_periph.h>
49144966Svkashyap#include <cam/cam_debug.h>
50144966Svkashyap#include <cam/cam_periph.h>
51144966Svkashyap
52144966Svkashyap#include <cam/scsi/scsi_all.h>
53144966Svkashyap#include <cam/scsi/scsi_message.h>
54144966Svkashyap
55144966Svkashyapstatic TW_VOID	twa_action(struct cam_sim *sim, union ccb *ccb);
56144966Svkashyapstatic TW_VOID	twa_poll(struct cam_sim *sim);
57144966Svkashyapstatic TW_VOID	twa_async(TW_VOID *callback_arg, TW_UINT32 code,
58144966Svkashyap	struct cam_path *path, TW_VOID *arg);
59144966Svkashyapstatic TW_VOID	twa_timeout(TW_VOID *arg);
60144966Svkashyapstatic TW_VOID	twa_bus_scan_cb(struct cam_periph *periph, union ccb *ccb);
61144966Svkashyap
62144966Svkashyapstatic TW_INT32	tw_osli_execute_scsi(struct tw_osli_req_context *req,
63144966Svkashyap	union ccb *ccb);
64144966Svkashyap
65144966Svkashyap
66144966Svkashyap
67144966Svkashyap/*
68144966Svkashyap * Function name:	tw_osli_cam_attach
69144966Svkashyap * Description:		Attaches the driver to CAM.
70144966Svkashyap *
71144966Svkashyap * Input:		sc	-- ptr to OSL internal ctlr context
72144966Svkashyap * Output:		None
73144966Svkashyap * Return value:	0	-- success
74144966Svkashyap *			non-zero-- failure
75144966Svkashyap */
76144966SvkashyapTW_INT32
77144966Svkashyaptw_osli_cam_attach(struct twa_softc *sc)
78144966Svkashyap{
79144966Svkashyap	struct cam_devq		*devq;
80144966Svkashyap	struct ccb_setasync	csa;
81144966Svkashyap	TW_INT32		error;
82144966Svkashyap
83144966Svkashyap	tw_osli_dbg_dprintf(3, sc, "entered");
84144966Svkashyap
85144966Svkashyap	/*
86144966Svkashyap	 * Create the device queue for our SIM.
87144966Svkashyap	 */
88144966Svkashyap	if ((devq = cam_simq_alloc(TW_OSLI_MAX_NUM_IOS)) == NULL) {
89144966Svkashyap		tw_osli_printf(sc, "error = %d",
90144966Svkashyap			TW_CL_SEVERITY_ERROR_STRING,
91144966Svkashyap			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
92144966Svkashyap			0x2100,
93144966Svkashyap			"Failed to create SIM device queue",
94144966Svkashyap			ENOMEM);
95144966Svkashyap		return(ENOMEM);
96144966Svkashyap	}
97144966Svkashyap
98144966Svkashyap	/*
99144966Svkashyap	 * Create a SIM entry.  Though we can support TW_OSLI_MAX_NUM_IOS
100144966Svkashyap	 * simultaneous requests, we claim to be able to handle only
101144966Svkashyap	 * (TW_OSLI_MAX_NUM_IOS - 1), so that we always have a request
102144966Svkashyap	 * packet available to service ioctls.
103144966Svkashyap	 */
104144966Svkashyap	tw_osli_dbg_dprintf(3, sc, "Calling cam_sim_alloc");
105144966Svkashyap	sc->sim = cam_sim_alloc(twa_action, twa_poll, "twa", sc,
106144966Svkashyap			device_get_unit(sc->bus_dev),
107144966Svkashyap			TW_OSLI_MAX_NUM_IOS - 1, 1, devq);
108144966Svkashyap	if (sc->sim == NULL) {
109144966Svkashyap		cam_simq_free(devq);
110144966Svkashyap		tw_osli_printf(sc, "error = %d",
111144966Svkashyap			TW_CL_SEVERITY_ERROR_STRING,
112144966Svkashyap			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
113144966Svkashyap			0x2101,
114144966Svkashyap			"Failed to create a SIM entry",
115144966Svkashyap			ENOMEM);
116144966Svkashyap		return(ENOMEM);
117144966Svkashyap	}
118144966Svkashyap
119144966Svkashyap	/*
120144966Svkashyap	 * Register the bus.
121144966Svkashyap	 */
122144966Svkashyap	tw_osli_dbg_dprintf(3, sc, "Calling xpt_bus_register");
123152213Svkashyap	mtx_lock(&Giant);
124144966Svkashyap	if (xpt_bus_register(sc->sim, 0) != CAM_SUCCESS) {
125144966Svkashyap		cam_sim_free(sc->sim, TRUE);
126144966Svkashyap		sc->sim = NULL; /* so cam_detach will not try to free it */
127144966Svkashyap		tw_osli_printf(sc, "error = %d",
128144966Svkashyap			TW_CL_SEVERITY_ERROR_STRING,
129144966Svkashyap			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
130144966Svkashyap			0x2102,
131144966Svkashyap			"Failed to register the bus",
132144966Svkashyap			ENXIO);
133144966Svkashyap		return(ENXIO);
134144966Svkashyap	}
135144966Svkashyap
136144966Svkashyap	tw_osli_dbg_dprintf(3, sc, "Calling xpt_create_path");
137144966Svkashyap	if (xpt_create_path(&sc->path, NULL,
138144966Svkashyap				cam_sim_path(sc->sim),
139144966Svkashyap				CAM_TARGET_WILDCARD,
140144966Svkashyap				CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
141144966Svkashyap		xpt_bus_deregister(cam_sim_path (sc->sim));
142144966Svkashyap		/* Passing TRUE to cam_sim_free will free the devq as well. */
143144966Svkashyap		cam_sim_free(sc->sim, TRUE);
144144966Svkashyap		tw_osli_printf(sc, "error = %d",
145144966Svkashyap			TW_CL_SEVERITY_ERROR_STRING,
146144966Svkashyap			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
147144966Svkashyap			0x2103,
148144966Svkashyap			"Failed to create path",
149144966Svkashyap			ENXIO);
150144966Svkashyap		return(ENXIO);
151144966Svkashyap	}
152144966Svkashyap
153144966Svkashyap	tw_osli_dbg_dprintf(3, sc, "Calling xpt_setup_ccb");
154144966Svkashyap	xpt_setup_ccb(&csa.ccb_h, sc->path, 5);
155144966Svkashyap	csa.ccb_h.func_code = XPT_SASYNC_CB;
156144966Svkashyap	csa.event_enable = AC_FOUND_DEVICE | AC_LOST_DEVICE;
157144966Svkashyap	csa.callback = twa_async;
158144966Svkashyap	csa.callback_arg = sc;
159144966Svkashyap	xpt_action((union ccb *)&csa);
160152213Svkashyap	mtx_unlock(&Giant);
161144966Svkashyap
162144966Svkashyap	tw_osli_dbg_dprintf(3, sc, "Calling tw_osli_request_bus_scan");
163144966Svkashyap	/*
164144966Svkashyap	 * Request a bus scan, so that CAM gets to know of
165144966Svkashyap	 * the logical units that we control.
166144966Svkashyap	 */
167144966Svkashyap	if ((error = tw_osli_request_bus_scan(sc)))
168144966Svkashyap		tw_osli_printf(sc, "error = %d",
169144966Svkashyap			TW_CL_SEVERITY_ERROR_STRING,
170144966Svkashyap			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
171144966Svkashyap			0x2104,
172144966Svkashyap			"Bus scan request to CAM failed",
173144966Svkashyap			error);
174144966Svkashyap
175144966Svkashyap	tw_osli_dbg_dprintf(3, sc, "exiting");
176144966Svkashyap	return(0);
177144966Svkashyap}
178144966Svkashyap
179144966Svkashyap
180144966Svkashyap
181144966Svkashyap/*
182144966Svkashyap * Function name:	tw_osli_cam_detach
183144966Svkashyap * Description:		Detaches the driver from CAM.
184144966Svkashyap *
185144966Svkashyap * Input:		sc	-- ptr to OSL internal ctlr context
186144966Svkashyap * Output:		None
187144966Svkashyap * Return value:	None
188144966Svkashyap */
189144966SvkashyapTW_VOID
190144966Svkashyaptw_osli_cam_detach(struct twa_softc *sc)
191144966Svkashyap{
192144966Svkashyap	tw_osli_dbg_dprintf(3, sc, "entered");
193144966Svkashyap
194147285Svkashyap	mtx_lock(&Giant);
195144966Svkashyap	if (sc->path)
196144966Svkashyap		xpt_free_path(sc->path);
197144966Svkashyap	if (sc->sim) {
198144966Svkashyap		xpt_bus_deregister(cam_sim_path(sc->sim));
199144966Svkashyap		/* Passing TRUE to cam_sim_free will free the devq as well. */
200144966Svkashyap		cam_sim_free(sc->sim, TRUE);
201144966Svkashyap	}
202147285Svkashyap	mtx_unlock(&Giant);
203144966Svkashyap}
204144966Svkashyap
205144966Svkashyap
206144966Svkashyap
207144966Svkashyap/*
208144966Svkashyap * Function name:	tw_osli_execute_scsi
209144966Svkashyap * Description:		Build a fw cmd, based on a CAM style ccb, and
210144966Svkashyap *			send it down.
211144966Svkashyap *
212144966Svkashyap * Input:		req	-- ptr to OSL internal request context
213144966Svkashyap *			ccb	-- ptr to CAM style ccb
214144966Svkashyap * Output:		None
215144966Svkashyap * Return value:	0	-- success
216144966Svkashyap *			non-zero-- failure
217144966Svkashyap */
218144966SvkashyapTW_INT32
219144966Svkashyaptw_osli_execute_scsi(struct tw_osli_req_context *req, union ccb *ccb)
220144966Svkashyap{
221144966Svkashyap	struct twa_softc		*sc = req->ctlr;
222144966Svkashyap	struct tw_cl_req_packet		*req_pkt;
223144966Svkashyap	struct tw_cl_scsi_req_packet	*scsi_req;
224144966Svkashyap	struct ccb_hdr			*ccb_h = &(ccb->ccb_h);
225144966Svkashyap	struct ccb_scsiio		*csio = &(ccb->csio);
226144966Svkashyap	TW_INT32			error;
227144966Svkashyap
228144966Svkashyap	tw_osli_dbg_dprintf(10, sc, "SCSI I/O request 0x%x",
229144966Svkashyap		csio->cdb_io.cdb_bytes[0]);
230144966Svkashyap
231144966Svkashyap	if (ccb_h->target_id >= TW_CL_MAX_NUM_UNITS) {
232144966Svkashyap		tw_osli_dbg_dprintf(3, sc, "Invalid target. PTL = %x %x %x",
233144966Svkashyap			ccb_h->path_id, ccb_h->target_id, ccb_h->target_lun);
234144966Svkashyap		ccb_h->status |= CAM_TID_INVALID;
235144966Svkashyap		xpt_done(ccb);
236144966Svkashyap		return(1);
237144966Svkashyap	}
238144966Svkashyap	if (ccb_h->target_lun >= TW_CL_MAX_NUM_LUNS) {
239144966Svkashyap		tw_osli_dbg_dprintf(3, sc, "Invalid lun. PTL = %x %x %x",
240144966Svkashyap			ccb_h->path_id, ccb_h->target_id, ccb_h->target_lun);
241144966Svkashyap		ccb_h->status |= CAM_LUN_INVALID;
242144966Svkashyap		xpt_done(ccb);
243144966Svkashyap		return(1);
244144966Svkashyap	}
245144966Svkashyap
246144966Svkashyap	if(ccb_h->flags & CAM_CDB_PHYS) {
247144966Svkashyap		tw_osli_printf(sc, "",
248144966Svkashyap			TW_CL_SEVERITY_ERROR_STRING,
249144966Svkashyap			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
250144966Svkashyap			0x2105,
251144966Svkashyap			"Physical CDB address!");
252144966Svkashyap		ccb_h->status = CAM_REQ_CMP_ERR;
253144966Svkashyap		xpt_done(ccb);
254144966Svkashyap		return(1);
255144966Svkashyap	}
256144966Svkashyap
257144966Svkashyap	/*
258144966Svkashyap	 * We are going to work on this request.  Mark it as enqueued (though
259144966Svkashyap	 * we don't actually queue it...)
260144966Svkashyap	 */
261144966Svkashyap	ccb_h->status |= CAM_SIM_QUEUED;
262144966Svkashyap
263144966Svkashyap	if((ccb_h->flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
264144966Svkashyap		if(ccb_h->flags & CAM_DIR_IN)
265144966Svkashyap			req->flags |= TW_OSLI_REQ_FLAGS_DATA_IN;
266144966Svkashyap		else
267144966Svkashyap			req->flags |= TW_OSLI_REQ_FLAGS_DATA_OUT;
268144966Svkashyap	}
269144966Svkashyap
270144966Svkashyap	/* Build the CL understood request packet for SCSI cmds. */
271144966Svkashyap	req_pkt = &req->req_pkt;
272144966Svkashyap	req_pkt->status = 0;
273144966Svkashyap	req_pkt->tw_osl_callback = tw_osl_complete_io;
274144966Svkashyap	scsi_req = &(req_pkt->gen_req_pkt.scsi_req);
275144966Svkashyap	scsi_req->unit = ccb_h->target_id;
276144966Svkashyap	scsi_req->lun = ccb_h->target_lun;
277144966Svkashyap	scsi_req->sense_len = 0;
278144966Svkashyap	scsi_req->sense_data = (TW_UINT8 *)(&csio->sense_data);
279144966Svkashyap	scsi_req->scsi_status = 0;
280144966Svkashyap	if(ccb_h->flags & CAM_CDB_POINTER)
281144966Svkashyap		scsi_req->cdb = csio->cdb_io.cdb_ptr;
282144966Svkashyap	else
283144966Svkashyap		scsi_req->cdb = csio->cdb_io.cdb_bytes;
284144966Svkashyap	scsi_req->cdb_len = csio->cdb_len;
285144966Svkashyap
286144966Svkashyap	if (!(ccb_h->flags & CAM_DATA_PHYS)) {
287144966Svkashyap		/* Virtual data addresses.  Need to convert them... */
288144966Svkashyap		tw_osli_dbg_dprintf(3, sc,
289144966Svkashyap			"XPT_SCSI_IO: Single virtual address!");
290144966Svkashyap		if (!(ccb_h->flags & CAM_SCATTER_VALID)) {
291144966Svkashyap			if (csio->dxfer_len > TW_CL_MAX_IO_SIZE) {
292144966Svkashyap				tw_osli_printf(sc, "size = %d",
293144966Svkashyap					TW_CL_SEVERITY_ERROR_STRING,
294144966Svkashyap					TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
295144966Svkashyap					0x2106,
296144966Svkashyap					"I/O size too big",
297144966Svkashyap					csio->dxfer_len);
298144966Svkashyap				ccb_h->status = CAM_REQ_TOO_BIG;
299144966Svkashyap				xpt_done(ccb);
300144966Svkashyap				return(1);
301144966Svkashyap			}
302144966Svkashyap
303144966Svkashyap			if ((req->length = csio->dxfer_len)) {
304144966Svkashyap				req->data = csio->data_ptr;
305144966Svkashyap				scsi_req->sgl_entries = 1;
306144966Svkashyap			}
307144966Svkashyap		} else {
308144966Svkashyap			tw_osli_printf(sc, "",
309144966Svkashyap				TW_CL_SEVERITY_ERROR_STRING,
310144966Svkashyap				TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
311144966Svkashyap				0x2107,
312144966Svkashyap				"XPT_SCSI_IO: Got SGList");
313144966Svkashyap			ccb_h->status = CAM_REQ_CMP_ERR;
314144966Svkashyap			xpt_done(ccb);
315144966Svkashyap			return(1);
316144966Svkashyap		}
317144966Svkashyap	} else {
318144966Svkashyap		/* Data addresses are physical. */
319144966Svkashyap		tw_osli_printf(sc, "",
320144966Svkashyap			TW_CL_SEVERITY_ERROR_STRING,
321144966Svkashyap			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
322144966Svkashyap			0x2108,
323144966Svkashyap			"XPT_SCSI_IO: Physical data addresses");
324144966Svkashyap		ccb_h->status = CAM_REQ_CMP_ERR;
325144966Svkashyap		ccb_h->status |= CAM_RELEASE_SIMQ;
326144966Svkashyap		ccb_h->status &= ~CAM_SIM_QUEUED;
327144966Svkashyap		xpt_done(ccb);
328144966Svkashyap		return(1);
329144966Svkashyap	}
330144966Svkashyap
331144966Svkashyap	ccb_h->timeout_ch = timeout(twa_timeout, req,
332144966Svkashyap		(ccb_h->timeout * hz) / 1000);
333144966Svkashyap	/*
334144966Svkashyap	 * twa_map_load_data_callback will fill in the SGL,
335144966Svkashyap	 * and submit the I/O.
336144966Svkashyap	 */
337144966Svkashyap	error = tw_osli_map_request(req);
338144966Svkashyap	return(error);
339144966Svkashyap}
340144966Svkashyap
341144966Svkashyap
342144966Svkashyap
343144966Svkashyap/*
344144966Svkashyap * Function name:	twa_action
345144966Svkashyap * Description:		Driver entry point for CAM's use.
346144966Svkashyap *
347144966Svkashyap * Input:		sim	-- sim corresponding to the ctlr
348144966Svkashyap *			ccb	-- ptr to CAM request
349144966Svkashyap * Output:		None
350144966Svkashyap * Return value:	None
351144966Svkashyap */
352144966SvkashyapTW_VOID
353144966Svkashyaptwa_action(struct cam_sim *sim, union ccb *ccb)
354144966Svkashyap{
355144966Svkashyap	struct twa_softc	*sc = (struct twa_softc *)cam_sim_softc(sim);
356144966Svkashyap	struct ccb_hdr		*ccb_h = &(ccb->ccb_h);
357144966Svkashyap
358144966Svkashyap	switch (ccb_h->func_code) {
359144966Svkashyap	case XPT_SCSI_IO:	/* SCSI I/O */
360144966Svkashyap	{
361144966Svkashyap		struct tw_osli_req_context	*req;
362144966Svkashyap
363144966Svkashyap		if ((sc->state & TW_OSLI_CTLR_STATE_SIMQ_FROZEN) ||
364144966Svkashyap				((req = tw_osli_get_request(sc)) == NULL)) {
365144966Svkashyap			tw_osli_dbg_dprintf(2, sc,
366144966Svkashyap				"simq frozen/Cannot get request pkt.");
367144966Svkashyap			/*
368144966Svkashyap			 * Freeze the simq to maintain ccb ordering.  The next
369144966Svkashyap			 * ccb that gets completed will unfreeze the simq.
370144966Svkashyap			 */
371144966Svkashyap			tw_osli_disallow_new_requests(sc);
372144966Svkashyap			ccb_h->status |= CAM_REQUEUE_REQ;
373144966Svkashyap			xpt_done(ccb);
374144966Svkashyap			break;
375144966Svkashyap		}
376144966Svkashyap		req->req_handle.osl_req_ctxt = req;
377144966Svkashyap		req->orig_req = ccb;
378144966Svkashyap		if (tw_osli_execute_scsi(req, ccb))
379144966Svkashyap			tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q);
380144966Svkashyap		break;
381144966Svkashyap	}
382144966Svkashyap
383144966Svkashyap	case XPT_ABORT:
384144966Svkashyap		tw_osli_dbg_dprintf(2, sc, "Abort request.");
385144966Svkashyap		ccb_h->status = CAM_UA_ABORT;
386144966Svkashyap		xpt_done(ccb);
387144966Svkashyap		break;
388144966Svkashyap
389144966Svkashyap	case XPT_RESET_BUS:
390144966Svkashyap		tw_cl_create_event(&(sc->ctlr_handle), TW_CL_TRUE,
391144966Svkashyap			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
392144966Svkashyap			0x2108, 0x3, TW_CL_SEVERITY_INFO_STRING,
393144966Svkashyap			"Received Reset Bus request from CAM",
394144966Svkashyap			" ");
395144966Svkashyap
396144966Svkashyap		if (tw_cl_reset_ctlr(&sc->ctlr_handle)) {
397144966Svkashyap			tw_cl_create_event(&(sc->ctlr_handle), TW_CL_TRUE,
398144966Svkashyap				TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
399144966Svkashyap				0x2109, 0x1, TW_CL_SEVERITY_ERROR_STRING,
400144966Svkashyap				"Failed to reset bus",
401144966Svkashyap				" ");
402144966Svkashyap			ccb_h->status = CAM_REQ_CMP_ERR;
403144966Svkashyap		}
404144966Svkashyap		else
405144966Svkashyap			ccb_h->status = CAM_REQ_CMP;
406144966Svkashyap
407144966Svkashyap		xpt_done(ccb);
408144966Svkashyap		break;
409144966Svkashyap
410144966Svkashyap	case XPT_SET_TRAN_SETTINGS:
411144966Svkashyap		tw_osli_dbg_dprintf(3, sc, "XPT_SET_TRAN_SETTINGS");
412144966Svkashyap
413144966Svkashyap		/*
414144966Svkashyap		 * This command is not supported, since it's very specific
415144966Svkashyap		 * to SCSI, and we are doing ATA.
416144966Svkashyap		 */
417144966Svkashyap  		ccb_h->status = CAM_FUNC_NOTAVAIL;
418144966Svkashyap  		xpt_done(ccb);
419144966Svkashyap  		break;
420144966Svkashyap
421144966Svkashyap	case XPT_GET_TRAN_SETTINGS:
422144966Svkashyap	{
423144966Svkashyap		struct ccb_trans_settings	*cts = &ccb->cts;
424144966Svkashyap
425144966Svkashyap		tw_osli_dbg_dprintf(3, sc, "XPT_GET_TRAN_SETTINGS");
426144966Svkashyap		cts->valid = (CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID);
427144966Svkashyap		cts->flags &= ~(CCB_TRANS_DISC_ENB | CCB_TRANS_TAG_ENB);
428144966Svkashyap		ccb_h->status = CAM_REQ_CMP;
429144966Svkashyap		xpt_done(ccb);
430144966Svkashyap		break;
431144966Svkashyap	}
432144966Svkashyap
433144966Svkashyap	case XPT_CALC_GEOMETRY:
434144966Svkashyap		tw_osli_dbg_dprintf(3, sc, "XPT_CALC_GEOMETRY");
435144966Svkashyap		cam_calc_geometry(&ccb->ccg, 1/* extended */);
436144966Svkashyap		xpt_done(ccb);
437144966Svkashyap		break;
438144966Svkashyap
439144966Svkashyap	case XPT_PATH_INQ:    /* Path inquiry -- get twa properties */
440144966Svkashyap	{
441144966Svkashyap		struct ccb_pathinq	*path_inq = &ccb->cpi;
442144966Svkashyap
443144966Svkashyap		tw_osli_dbg_dprintf(3, sc, "XPT_PATH_INQ request");
444144966Svkashyap
445144966Svkashyap		path_inq->version_num = 1;
446144966Svkashyap		path_inq->hba_inquiry = 0;
447144966Svkashyap		path_inq->target_sprt = 0;
448144966Svkashyap		path_inq->hba_misc = 0;
449144966Svkashyap		path_inq->hba_eng_cnt = 0;
450144966Svkashyap		path_inq->max_target = TW_CL_MAX_NUM_UNITS;
451144966Svkashyap		path_inq->max_lun = TW_CL_MAX_NUM_LUNS - 1;
452144966Svkashyap		path_inq->unit_number = cam_sim_unit(sim);
453144966Svkashyap		path_inq->bus_id = cam_sim_bus(sim);
454152213Svkashyap		path_inq->initiator_id = TW_CL_MAX_NUM_UNITS;
455144966Svkashyap		path_inq->base_transfer_speed = 100000;
456144966Svkashyap		strncpy(path_inq->sim_vid, "FreeBSD", SIM_IDLEN);
457144966Svkashyap		strncpy(path_inq->hba_vid, "3ware", HBA_IDLEN);
458144966Svkashyap		strncpy(path_inq->dev_name, cam_sim_name(sim), DEV_IDLEN);
459144966Svkashyap		ccb_h->status = CAM_REQ_CMP;
460144966Svkashyap		xpt_done(ccb);
461144966Svkashyap		break;
462144966Svkashyap	}
463144966Svkashyap
464144966Svkashyap	default:
465144966Svkashyap		tw_osli_dbg_dprintf(3, sc, "func_code = %x", ccb_h->func_code);
466144966Svkashyap		ccb_h->status = CAM_REQ_INVALID;
467144966Svkashyap		xpt_done(ccb);
468144966Svkashyap		break;
469144966Svkashyap	}
470144966Svkashyap}
471144966Svkashyap
472144966Svkashyap
473144966Svkashyap
474144966Svkashyap/*
475144966Svkashyap * Function name:	twa_poll
476144966Svkashyap * Description:		Driver entry point called when interrupts are not
477144966Svkashyap *			available.
478144966Svkashyap *
479144966Svkashyap * Input:		sim	-- sim corresponding to the controller
480144966Svkashyap * Output:		None
481144966Svkashyap * Return value:	None
482144966Svkashyap */
483144966SvkashyapTW_VOID
484144966Svkashyaptwa_poll(struct cam_sim *sim)
485144966Svkashyap{
486144966Svkashyap	struct twa_softc *sc = (struct twa_softc *)(cam_sim_softc(sim));
487144966Svkashyap
488144966Svkashyap	tw_osli_dbg_dprintf(3, sc, "entering; sc = %p", sc);
489145688Svkashyap	/*
490145688Svkashyap	 * It's been observed that twa_poll can get called (from
491145688Svkashyap	 * dashutdown --> xpt_polled_action) even when interrupts are
492145688Svkashyap	 * active, in which case, the ISR might clear the interrupt,
493145688Svkashyap	 * leaving the call to tw_cl_interrupt below, no way of determining
494145688Svkashyap	 * that the response from firmware is ready, resulting in
495145688Svkashyap	 * tw_cl_deferred_interrupt never getting called.  To cover this case,
496145688Svkashyap	 * we will make the call to tw_cl_deferred_interrupt not dependent
497145688Svkashyap	 * on the return value from tw_cl_interrupt.
498145688Svkashyap	 */
499145688Svkashyap	tw_cl_interrupt(&(sc->ctlr_handle));
500145688Svkashyap	tw_cl_deferred_interrupt(&(sc->ctlr_handle));
501144966Svkashyap	tw_osli_dbg_dprintf(3, sc, "exiting; sc = %p", sc);
502144966Svkashyap}
503144966Svkashyap
504144966Svkashyap
505144966Svkashyap
506144966Svkashyap/*
507144966Svkashyap * Function name:	twa_async
508144966Svkashyap * Description:		Driver entry point for CAM to notify driver of special
509144966Svkashyap *			events.  We don't use this for now.
510144966Svkashyap *
511144966Svkashyap * Input:		callback_arg	-- ptr to per ctlr structure
512144966Svkashyap *			code		-- code associated with the event
513144966Svkashyap *			path		-- cam path
514144966Svkashyap *			arg		--
515144966Svkashyap * Output:		None
516144966Svkashyap * Return value:	0	-- success
517144966Svkashyap *			non-zero-- failure
518144966Svkashyap */
519144966SvkashyapTW_VOID
520144966Svkashyaptwa_async(TW_VOID *callback_arg, TW_UINT32 code,
521144966Svkashyap	struct cam_path *path, TW_VOID *arg)
522144966Svkashyap{
523144966Svkashyap#ifdef TW_OSL_DEBUG
524144966Svkashyap	struct twa_softc *sc = (struct twa_softc *)callback_arg;
525144966Svkashyap#endif /* TW_OSL_DEBUG */
526144966Svkashyap
527144966Svkashyap	tw_osli_dbg_dprintf(3, sc, "sc = %p, code = %x, path = %p, arg = %p",
528144966Svkashyap		sc, code, path, arg);
529144966Svkashyap}
530144966Svkashyap
531144966Svkashyap
532144966Svkashyap
533144966Svkashyap/*
534144966Svkashyap * Function name:	twa_timeout
535144966Svkashyap * Description:		Driver entry point for being alerted on a request
536144966Svkashyap *			timing out.
537144966Svkashyap *
538144966Svkashyap * Input:		arg	-- ptr to timed out request
539144966Svkashyap * Output:		None
540144966Svkashyap * Return value:	None
541144966Svkashyap */
542144966Svkashyapstatic TW_VOID
543144966Svkashyaptwa_timeout(TW_VOID *arg)
544144966Svkashyap{
545144966Svkashyap	struct tw_osli_req_context	*req =
546144966Svkashyap		(struct tw_osli_req_context *)arg;
547144966Svkashyap
548144966Svkashyap	tw_cl_create_event(&(req->ctlr->ctlr_handle), TW_CL_TRUE,
549144966Svkashyap		TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
550144966Svkashyap		0x210B, 0x1, TW_CL_SEVERITY_ERROR_STRING,
551144966Svkashyap		"Request timed out!",
552144966Svkashyap		"request = %p", req);
553144966Svkashyap	tw_cl_reset_ctlr(&(req->ctlr->ctlr_handle));
554144966Svkashyap}
555144966Svkashyap
556144966Svkashyap
557144966Svkashyap
558144966Svkashyap/*
559144966Svkashyap * Function name:	tw_osli_request_bus_scan
560144966Svkashyap * Description:		Requests CAM for a scan of the bus.
561144966Svkashyap *
562144966Svkashyap * Input:		sc	-- ptr to per ctlr structure
563144966Svkashyap * Output:		None
564144966Svkashyap * Return value:	0	-- success
565144966Svkashyap *			non-zero-- failure
566144966Svkashyap */
567144966SvkashyapTW_INT32
568144966Svkashyaptw_osli_request_bus_scan(struct twa_softc *sc)
569144966Svkashyap{
570144966Svkashyap	struct cam_path	*path;
571144966Svkashyap	union ccb	*ccb;
572144966Svkashyap
573144966Svkashyap	tw_osli_dbg_dprintf(3, sc, "entering");
574144966Svkashyap
575152213Svkashyap	/* If we get here before sc->sim is initialized, return an error. */
576152213Svkashyap	if (!(sc->sim))
577152213Svkashyap		return(ENXIO);
578144966Svkashyap	if ((ccb = malloc(sizeof(union ccb), M_TEMP, M_WAITOK)) == NULL)
579144966Svkashyap		return(ENOMEM);
580144966Svkashyap	bzero(ccb, sizeof(union ccb));
581147285Svkashyap	mtx_lock(&Giant);
582144966Svkashyap	if (xpt_create_path(&path, xpt_periph, cam_sim_path(sc->sim),
583144966Svkashyap		CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP)
584144966Svkashyap		return(EIO);
585144966Svkashyap
586144966Svkashyap	xpt_setup_ccb(&ccb->ccb_h, path, 5);
587144966Svkashyap	ccb->ccb_h.func_code = XPT_SCAN_BUS;
588144966Svkashyap	ccb->ccb_h.cbfcnp = twa_bus_scan_cb;
589144966Svkashyap	ccb->crcn.flags = CAM_FLAG_NONE;
590144966Svkashyap	xpt_action(ccb);
591147285Svkashyap	mtx_unlock(&Giant);
592144966Svkashyap	return(0);
593144966Svkashyap}
594144966Svkashyap
595144966Svkashyap
596144966Svkashyap
597144966Svkashyap/*
598144966Svkashyap * Function name:	twa_bus_scan_cb
599144966Svkashyap * Description:		Callback from CAM on a bus scan request.
600144966Svkashyap *
601144966Svkashyap * Input:		periph	-- we don't use this
602144966Svkashyap *			ccb	-- bus scan request ccb that we sent to CAM
603144966Svkashyap * Output:		None
604144966Svkashyap * Return value:	None
605144966Svkashyap */
606144966Svkashyapstatic TW_VOID
607144966Svkashyaptwa_bus_scan_cb(struct cam_periph *periph, union ccb *ccb)
608144966Svkashyap{
609144966Svkashyap	tw_osli_dbg_printf(3, "entering");
610144966Svkashyap
611144966Svkashyap	if (ccb->ccb_h.status != CAM_REQ_CMP)
612144966Svkashyap		printf("cam_scan_callback: failure status = %x\n",
613144966Svkashyap			ccb->ccb_h.status);
614144966Svkashyap	else
615144966Svkashyap		tw_osli_dbg_printf(3, "success");
616144966Svkashyap
617144966Svkashyap	xpt_free_path(ccb->ccb_h.path);
618144966Svkashyap	free(ccb, M_TEMP);
619144966Svkashyap}
620144966Svkashyap
621144966Svkashyap
622144966Svkashyap
623144966Svkashyap/*
624144966Svkashyap * Function name:	tw_osli_allow_new_requests
625144966Svkashyap * Description:		Sets the appropriate status bits in a ccb such that,
626144966Svkashyap *			when the ccb is completed by a call to xpt_done,
627144966Svkashyap *			CAM knows that it's ok to unfreeze the flow of new
628144966Svkashyap *			requests to this controller, if the flow is frozen.
629144966Svkashyap *
630144966Svkashyap * Input:		sc	-- ptr to OSL internal ctlr context
631144966Svkashyap *			ccb	-- ptr to CAM request
632144966Svkashyap * Output:		None
633144966Svkashyap * Return value:	None
634144966Svkashyap */
635144966SvkashyapTW_VOID
636144966Svkashyaptw_osli_allow_new_requests(struct twa_softc *sc, TW_VOID *ccb)
637144966Svkashyap{
638144966Svkashyap	((union ccb *)(ccb))->ccb_h.status |= CAM_RELEASE_SIMQ;
639144966Svkashyap	sc->state &= ~TW_OSLI_CTLR_STATE_SIMQ_FROZEN;
640144966Svkashyap}
641144966Svkashyap
642144966Svkashyap
643144966Svkashyap
644144966Svkashyap/*
645144966Svkashyap * Function name:	tw_osli_disallow_new_requests
646144966Svkashyap * Description:		Calls the appropriate CAM function, so as to freeze
647144966Svkashyap *			the flow of new requests from CAM to this controller.
648144966Svkashyap *
649144966Svkashyap * Input:		sc	-- ptr to OSL internal ctlr context
650144966Svkashyap * Output:		None
651144966Svkashyap * Return value:	None
652144966Svkashyap */
653144966SvkashyapTW_VOID
654144966Svkashyaptw_osli_disallow_new_requests(struct twa_softc *sc)
655144966Svkashyap{
656152213Svkashyap	mtx_lock(&Giant);
657144966Svkashyap	xpt_freeze_simq(sc->sim, 1);
658152213Svkashyap	mtx_unlock(&Giant);
659144966Svkashyap	sc->state |= TW_OSLI_CTLR_STATE_SIMQ_FROZEN;
660144966Svkashyap}
661144966Svkashyap
662144966Svkashyap
663144966Svkashyap
664144966Svkashyap/*
665152213Svkashyap * Function name:	tw_osl_ctlr_busy
666152213Svkashyap * Description:		CL calls this function on cmd queue full or otherwise,
667152213Svkashyap *			when it is too busy to accept new requests.
668152213Svkashyap *
669152213Svkashyap * Input:		ctlr_handle	-- ptr to controller handle
670152213Svkashyap *			req_handle	-- ptr to request handle sent by OSL.
671152213Svkashyap * Output:		None
672152213Svkashyap * Return value:	None
673152213Svkashyap */
674152213SvkashyapTW_VOID
675152213Svkashyaptw_osl_ctlr_busy(struct tw_cl_ctlr_handle *ctlr_handle,
676152213Svkashyap	struct tw_cl_req_handle *req_handle)
677152213Svkashyap{
678152213Svkashyap	tw_osli_disallow_new_requests(ctlr_handle->osl_ctlr_ctxt);
679152213Svkashyap}
680152213Svkashyap
681152213Svkashyap
682152213Svkashyap
683152213Svkashyap/*
684144966Svkashyap * Function name:	tw_osl_scan_bus
685144966Svkashyap * Description:		CL calls this function to request for a bus scan.
686144966Svkashyap *
687144966Svkashyap * Input:		ctlr_handle	-- ptr to controller handle
688144966Svkashyap * Output:		None
689144966Svkashyap * Return value:	None
690144966Svkashyap */
691144966SvkashyapTW_VOID
692144966Svkashyaptw_osl_scan_bus(struct tw_cl_ctlr_handle *ctlr_handle)
693144966Svkashyap{
694144966Svkashyap	struct twa_softc	*sc = ctlr_handle->osl_ctlr_ctxt;
695144966Svkashyap	TW_INT32		error;
696144966Svkashyap
697144966Svkashyap	if ((error = tw_osli_request_bus_scan(sc)))
698144966Svkashyap		tw_osli_printf(sc, "error = %d",
699144966Svkashyap			TW_CL_SEVERITY_ERROR_STRING,
700144966Svkashyap			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
701144966Svkashyap			0x2109,
702144966Svkashyap			"Bus scan request to CAM failed",
703144966Svkashyap			error);
704144966Svkashyap}
705144966Svkashyap
706144966Svkashyap
707144966Svkashyap
708144966Svkashyap/*
709144966Svkashyap * Function name:	tw_osl_complete_io
710144966Svkashyap * Description:		Called to complete CAM scsi requests.
711144966Svkashyap *
712144966Svkashyap * Input:		req_handle	-- ptr to request handle
713144966Svkashyap * Output:		None
714144966Svkashyap * Return value:	None
715144966Svkashyap */
716144966SvkashyapTW_VOID
717144966Svkashyaptw_osl_complete_io(struct tw_cl_req_handle *req_handle)
718144966Svkashyap{
719144966Svkashyap	struct tw_osli_req_context	*req = req_handle->osl_req_ctxt;
720144966Svkashyap	struct tw_cl_req_packet		*req_pkt =
721144966Svkashyap		(struct tw_cl_req_packet *)(&req->req_pkt);
722144966Svkashyap	struct tw_cl_scsi_req_packet	*scsi_req;
723144966Svkashyap	struct twa_softc		*sc = req->ctlr;
724144966Svkashyap	union ccb			*ccb = (union ccb *)(req->orig_req);
725144966Svkashyap
726144966Svkashyap	tw_osli_dbg_dprintf(10, sc, "entering");
727144966Svkashyap
728144966Svkashyap	if (req->state != TW_OSLI_REQ_STATE_BUSY)
729144966Svkashyap		tw_osli_printf(sc, "request = %p, status = %d",
730144966Svkashyap			TW_CL_SEVERITY_ERROR_STRING,
731144966Svkashyap			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
732144966Svkashyap			0x210A,
733144966Svkashyap			"Unposted command completed!!",
734144966Svkashyap			req, req->state);
735144966Svkashyap
736144966Svkashyap	/*
737144966Svkashyap	 * Remove request from the busy queue.  Just mark it complete.
738144966Svkashyap	 * There's no need to move it into the complete queue as we are
739144966Svkashyap	 * going to be done with it right now.
740144966Svkashyap	 */
741144966Svkashyap	req->state = TW_OSLI_REQ_STATE_COMPLETE;
742144966Svkashyap	tw_osli_req_q_remove_item(req, TW_OSLI_BUSY_Q);
743144966Svkashyap
744144966Svkashyap	tw_osli_unmap_request(req);
745144966Svkashyap
746144966Svkashyap	untimeout(twa_timeout, req, ccb->ccb_h.timeout_ch);
747144966Svkashyap	if (req->error_code) {
748144966Svkashyap		/* This request never got submitted to the firmware. */
749144966Svkashyap		if (req->error_code == EBUSY) {
750144966Svkashyap			/*
751152213Svkashyap			 * Cmd queue is full, or the Common Layer is out of
752152213Svkashyap			 * resources.  The simq will already have been frozen
753152213Svkashyap			 * by CL's call to tw_osl_ctlr_busy, and this will
754152213Svkashyap			 * maintain ccb ordering.  The next ccb that gets
755144966Svkashyap			 * completed will unfreeze the simq.
756144966Svkashyap			 */
757144966Svkashyap			ccb->ccb_h.status |= CAM_REQUEUE_REQ;
758144966Svkashyap		}
759144966Svkashyap		else if (req->error_code == EFBIG)
760144966Svkashyap			ccb->ccb_h.status = CAM_REQ_TOO_BIG;
761144966Svkashyap		else
762144966Svkashyap			ccb->ccb_h.status = CAM_REQ_CMP_ERR;
763144966Svkashyap	} else {
764144966Svkashyap		scsi_req = &(req_pkt->gen_req_pkt.scsi_req);
765144966Svkashyap		if (req_pkt->status == TW_CL_ERR_REQ_SUCCESS)
766144966Svkashyap			ccb->ccb_h.status = CAM_REQ_CMP;
767144966Svkashyap		else {
768144966Svkashyap			if (req_pkt->status & TW_CL_ERR_REQ_INVALID_TARGET)
769144966Svkashyap				ccb->ccb_h.status |= CAM_TID_INVALID;
770144966Svkashyap			else if (req_pkt->status & TW_CL_ERR_REQ_INVALID_LUN)
771144966Svkashyap				ccb->ccb_h.status |= CAM_LUN_INVALID;
772144966Svkashyap			else if (req_pkt->status & TW_CL_ERR_REQ_SCSI_ERROR)
773144966Svkashyap				ccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
774144966Svkashyap			else if (req_pkt->status & TW_CL_ERR_REQ_BUS_RESET)
775144966Svkashyap				ccb->ccb_h.status |= CAM_SCSI_BUS_RESET;
776144966Svkashyap			/*
777144966Svkashyap			 * If none of the above errors occurred, simply
778144966Svkashyap			 * mark completion error.
779144966Svkashyap			 */
780144966Svkashyap			if (ccb->ccb_h.status == 0)
781144966Svkashyap				ccb->ccb_h.status = CAM_REQ_CMP_ERR;
782144966Svkashyap
783144966Svkashyap			if (req_pkt->status & TW_CL_ERR_REQ_AUTO_SENSE_VALID) {
784144966Svkashyap				ccb->csio.sense_len = scsi_req->sense_len;
785144966Svkashyap				ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
786144966Svkashyap			}
787144966Svkashyap		}
788144966Svkashyap
789144966Svkashyap		ccb->csio.scsi_status = scsi_req->scsi_status;
790144966Svkashyap		/* If simq is frozen, unfreeze it. */
791144966Svkashyap		if (sc->state & TW_OSLI_CTLR_STATE_SIMQ_FROZEN)
792144966Svkashyap			tw_osli_allow_new_requests(sc, (TW_VOID *)ccb);
793144966Svkashyap	}
794144966Svkashyap
795144966Svkashyap	ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
796144966Svkashyap	xpt_done(ccb);
797144966Svkashyap	if (! req->error_code)
798144966Svkashyap		 /* twa_action will free the request otherwise */
799144966Svkashyap		tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q);
800144966Svkashyap}
801144966Svkashyap
802