xref: /dflybsd-src/sys/dev/raid/twa/tw_osl_cam.c (revision a712521bb73cda40492b717724848e056e176a74)
1df54c2f9SSascha Wildner /*
2df54c2f9SSascha Wildner  * Copyright (c) 2004-07 Applied Micro Circuits Corporation.
3df54c2f9SSascha Wildner  * Copyright (c) 2004-05 Vinod Kashyap.
4df54c2f9SSascha Wildner  * All rights reserved.
5df54c2f9SSascha Wildner  *
6df54c2f9SSascha Wildner  * Redistribution and use in source and binary forms, with or without
7df54c2f9SSascha Wildner  * modification, are permitted provided that the following conditions
8df54c2f9SSascha Wildner  * are met:
9df54c2f9SSascha Wildner  * 1. Redistributions of source code must retain the above copyright
10df54c2f9SSascha Wildner  *    notice, this list of conditions and the following disclaimer.
11df54c2f9SSascha Wildner  * 2. Redistributions in binary form must reproduce the above copyright
12df54c2f9SSascha Wildner  *    notice, this list of conditions and the following disclaimer in the
13df54c2f9SSascha Wildner  *    documentation and/or other materials provided with the distribution.
14df54c2f9SSascha Wildner  *
15df54c2f9SSascha Wildner  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16df54c2f9SSascha Wildner  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17df54c2f9SSascha Wildner  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18df54c2f9SSascha Wildner  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19df54c2f9SSascha Wildner  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20df54c2f9SSascha Wildner  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21df54c2f9SSascha Wildner  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22df54c2f9SSascha Wildner  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23df54c2f9SSascha Wildner  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24df54c2f9SSascha Wildner  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25df54c2f9SSascha Wildner  * SUCH DAMAGE.
26df54c2f9SSascha Wildner  *
2785b59853SSascha Wildner  *	$FreeBSD: src/sys/dev/twa/tw_osl_cam.c,v 1.16 2012/06/22 21:46:41 mav Exp $
28df54c2f9SSascha Wildner  */
29df54c2f9SSascha Wildner 
30df54c2f9SSascha Wildner /*
31df54c2f9SSascha Wildner  * AMCC'S 3ware driver for 9000 series storage controllers.
32df54c2f9SSascha Wildner  *
33df54c2f9SSascha Wildner  * Author: Vinod Kashyap
34df54c2f9SSascha Wildner  * Modifications by: Adam Radford
35df54c2f9SSascha Wildner  * Modifications by: Manjunath Ranganathaiah
36df54c2f9SSascha Wildner  */
37df54c2f9SSascha Wildner 
38df54c2f9SSascha Wildner 
39df54c2f9SSascha Wildner /*
40df54c2f9SSascha Wildner  * FreeBSD CAM related functions.
41df54c2f9SSascha Wildner  */
42df54c2f9SSascha Wildner 
43df54c2f9SSascha Wildner 
44df54c2f9SSascha Wildner #include <dev/raid/twa/tw_osl_includes.h>
45df54c2f9SSascha Wildner 
46df54c2f9SSascha Wildner #include <bus/cam/cam.h>
47df54c2f9SSascha Wildner #include <bus/cam/cam_ccb.h>
48df54c2f9SSascha Wildner #include <bus/cam/cam_sim.h>
49df54c2f9SSascha Wildner #include <bus/cam/cam_xpt_sim.h>
50df54c2f9SSascha Wildner #include <bus/cam/cam_debug.h>
51df54c2f9SSascha Wildner #include <bus/cam/cam_periph.h>
52df54c2f9SSascha Wildner #include <bus/cam/cam_xpt_periph.h>
53df54c2f9SSascha Wildner 
54df54c2f9SSascha Wildner #include <bus/cam/scsi/scsi_all.h>
55df54c2f9SSascha Wildner #include <bus/cam/scsi/scsi_message.h>
56df54c2f9SSascha Wildner 
57df54c2f9SSascha Wildner static TW_VOID	twa_action(struct cam_sim *sim, union ccb *ccb);
58df54c2f9SSascha Wildner static TW_VOID	twa_poll(struct cam_sim *sim);
59df54c2f9SSascha Wildner static TW_VOID	twa_bus_scan_cb(struct cam_periph *periph, union ccb *ccb);
60df54c2f9SSascha Wildner 
61df54c2f9SSascha Wildner static TW_INT32	tw_osli_execute_scsi(struct tw_osli_req_context *req,
62df54c2f9SSascha Wildner 	union ccb *ccb);
63df54c2f9SSascha Wildner 
64df54c2f9SSascha Wildner 
65df54c2f9SSascha Wildner 
66df54c2f9SSascha Wildner /*
67df54c2f9SSascha Wildner  * Function name:	tw_osli_cam_attach
68df54c2f9SSascha Wildner  * Description:		Attaches the driver to CAM.
69df54c2f9SSascha Wildner  *
70df54c2f9SSascha Wildner  * Input:		sc	-- ptr to OSL internal ctlr context
71df54c2f9SSascha Wildner  * Output:		None
72df54c2f9SSascha Wildner  * Return value:	0	-- success
73df54c2f9SSascha Wildner  *			non-zero-- failure
74df54c2f9SSascha Wildner  */
75df54c2f9SSascha Wildner TW_INT32
76df54c2f9SSascha Wildner tw_osli_cam_attach(struct twa_softc *sc)
77df54c2f9SSascha Wildner {
78df54c2f9SSascha Wildner 	struct cam_devq		*devq;
790ae4d753SSascha Wildner 	TW_INT32		error;
80df54c2f9SSascha Wildner 
81df54c2f9SSascha Wildner 	tw_osli_dbg_dprintf(3, sc, "entered");
82df54c2f9SSascha Wildner 
83df54c2f9SSascha Wildner 	/*
84df54c2f9SSascha Wildner 	 * Create the device queue for our SIM.
85df54c2f9SSascha Wildner 	 */
864fbf05f9SSascha Wildner 	if ((devq = cam_simq_alloc(TW_OSLI_MAX_NUM_IOS)) == NULL) {
87df54c2f9SSascha Wildner 		tw_osli_printf(sc, "error = %d",
88df54c2f9SSascha Wildner 			TW_CL_SEVERITY_ERROR_STRING,
89df54c2f9SSascha Wildner 			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
90df54c2f9SSascha Wildner 			0x2100,
91df54c2f9SSascha Wildner 			"Failed to create SIM device queue",
92df54c2f9SSascha Wildner 			ENOMEM);
93df54c2f9SSascha Wildner 		return(ENOMEM);
94df54c2f9SSascha Wildner 	}
95df54c2f9SSascha Wildner 
96df54c2f9SSascha Wildner 	/*
97df54c2f9SSascha Wildner 	 * Create a SIM entry.  Though we can support TW_OSLI_MAX_NUM_REQUESTS
98df54c2f9SSascha Wildner 	 * simultaneous requests, we claim to be able to handle only
99df54c2f9SSascha Wildner 	 * TW_OSLI_MAX_NUM_IOS (two less), so that we always have a request
100df54c2f9SSascha Wildner 	 * packet available to service ioctls and AENs.
101df54c2f9SSascha Wildner 	 */
102df54c2f9SSascha Wildner 	tw_osli_dbg_dprintf(3, sc, "Calling cam_sim_alloc");
103df54c2f9SSascha Wildner 	sc->sim = cam_sim_alloc(twa_action, twa_poll, "twa", sc,
104df54c2f9SSascha Wildner 			device_get_unit(sc->bus_dev), sc->sim_lock,
105df54c2f9SSascha Wildner 			TW_OSLI_MAX_NUM_IOS, 1, devq);
1060ae4d753SSascha Wildner 	cam_simq_release(devq);
107*a712521bSSascha Wildner 	if (sc->sim == NULL) {
108df54c2f9SSascha Wildner 		tw_osli_printf(sc, "error = %d",
109df54c2f9SSascha Wildner 			TW_CL_SEVERITY_ERROR_STRING,
110df54c2f9SSascha Wildner 			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
111df54c2f9SSascha Wildner 			0x2101,
112df54c2f9SSascha Wildner 			"Failed to create a SIM entry",
113df54c2f9SSascha Wildner 			ENOMEM);
114df54c2f9SSascha Wildner 		return(ENOMEM);
115df54c2f9SSascha Wildner 	}
116df54c2f9SSascha Wildner 
117df54c2f9SSascha Wildner 	/*
118df54c2f9SSascha Wildner 	 * Register the bus.
119df54c2f9SSascha Wildner 	 */
120df54c2f9SSascha Wildner 	tw_osli_dbg_dprintf(3, sc, "Calling xpt_bus_register");
121df54c2f9SSascha Wildner 	lockmgr(sc->sim_lock, LK_EXCLUSIVE);
122df54c2f9SSascha Wildner 	if (xpt_bus_register(sc->sim, 0) != CAM_SUCCESS) {
123df54c2f9SSascha Wildner 		cam_sim_free(sc->sim);
124df54c2f9SSascha Wildner 		sc->sim = NULL; /* so cam_detach will not try to free it */
125df54c2f9SSascha Wildner 		tw_osli_printf(sc, "error = %d",
126df54c2f9SSascha Wildner 			TW_CL_SEVERITY_ERROR_STRING,
127df54c2f9SSascha Wildner 			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
128df54c2f9SSascha Wildner 			0x2102,
129df54c2f9SSascha Wildner 			"Failed to register the bus",
130df54c2f9SSascha Wildner 			ENXIO);
131df54c2f9SSascha Wildner 		lockmgr(sc->sim_lock, LK_RELEASE);
132df54c2f9SSascha Wildner 		return(ENXIO);
133df54c2f9SSascha Wildner 	}
134df54c2f9SSascha Wildner 
135df54c2f9SSascha Wildner 	tw_osli_dbg_dprintf(3, sc, "Calling xpt_create_path");
136df54c2f9SSascha Wildner 	if (xpt_create_path(&sc->path, NULL,
137df54c2f9SSascha Wildner 				cam_sim_path(sc->sim),
138df54c2f9SSascha Wildner 				CAM_TARGET_WILDCARD,
139df54c2f9SSascha Wildner 				CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
140df54c2f9SSascha Wildner 		xpt_bus_deregister(cam_sim_path (sc->sim));
141df54c2f9SSascha Wildner 		cam_sim_free(sc->sim);
1420ae4d753SSascha Wildner 		sc->sim = NULL; /* so cam_detach will not try to free it */
143df54c2f9SSascha Wildner 		tw_osli_printf(sc, "error = %d",
144df54c2f9SSascha Wildner 			TW_CL_SEVERITY_ERROR_STRING,
145df54c2f9SSascha Wildner 			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
146df54c2f9SSascha Wildner 			0x2103,
147df54c2f9SSascha Wildner 			"Failed to create path",
148df54c2f9SSascha Wildner 			ENXIO);
149df54c2f9SSascha Wildner 		lockmgr(sc->sim_lock, LK_RELEASE);
150df54c2f9SSascha Wildner 		return(ENXIO);
151df54c2f9SSascha Wildner 	}
152df54c2f9SSascha Wildner 	lockmgr(sc->sim_lock, LK_RELEASE);
153df54c2f9SSascha Wildner 
1540ae4d753SSascha Wildner 	tw_osli_dbg_dprintf(3, sc, "Calling tw_osli_request_bus_scan");
1550ae4d753SSascha Wildner 	/*
1560ae4d753SSascha Wildner 	 * Request a bus scan, so that CAM gets to know of
1570ae4d753SSascha Wildner 	 * the logical units that we control.
1580ae4d753SSascha Wildner 	 */
1590ae4d753SSascha Wildner 	if ((error = tw_osli_request_bus_scan(sc)))
1600ae4d753SSascha Wildner 		tw_osli_printf(sc, "error = %d",
1610ae4d753SSascha Wildner 			TW_CL_SEVERITY_ERROR_STRING,
1620ae4d753SSascha Wildner 			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
1630ae4d753SSascha Wildner 			0x2104,
1640ae4d753SSascha Wildner 			"Bus scan request to CAM failed",
1650ae4d753SSascha Wildner 			error);
1660ae4d753SSascha Wildner 
167df54c2f9SSascha Wildner 	tw_osli_dbg_dprintf(3, sc, "exiting");
168df54c2f9SSascha Wildner 	return(0);
169df54c2f9SSascha Wildner }
170df54c2f9SSascha Wildner 
171df54c2f9SSascha Wildner 
172df54c2f9SSascha Wildner 
173df54c2f9SSascha Wildner /*
174df54c2f9SSascha Wildner  * Function name:	tw_osli_cam_detach
175df54c2f9SSascha Wildner  * Description:		Detaches the driver from CAM.
176df54c2f9SSascha Wildner  *
177df54c2f9SSascha Wildner  * Input:		sc	-- ptr to OSL internal ctlr context
178df54c2f9SSascha Wildner  * Output:		None
179df54c2f9SSascha Wildner  * Return value:	None
180df54c2f9SSascha Wildner  */
181df54c2f9SSascha Wildner TW_VOID
182df54c2f9SSascha Wildner tw_osli_cam_detach(struct twa_softc *sc)
183df54c2f9SSascha Wildner {
184df54c2f9SSascha Wildner 	tw_osli_dbg_dprintf(3, sc, "entered");
185df54c2f9SSascha Wildner 
186df54c2f9SSascha Wildner 	lockmgr(sc->sim_lock, LK_EXCLUSIVE);
187df54c2f9SSascha Wildner 
188df54c2f9SSascha Wildner 	if (sc->path)
189df54c2f9SSascha Wildner 		xpt_free_path(sc->path);
190df54c2f9SSascha Wildner 	if (sc->sim) {
191df54c2f9SSascha Wildner 		xpt_bus_deregister(cam_sim_path(sc->sim));
192df54c2f9SSascha Wildner 		/* Passing TRUE to cam_sim_free will free the devq as well. */
193df54c2f9SSascha Wildner 		cam_sim_free(sc->sim);
194df54c2f9SSascha Wildner 	}
195df54c2f9SSascha Wildner 	/* It's ok have 1 hold count while destroying the mutex */
196df54c2f9SSascha Wildner 	lockuninit(sc->sim_lock);
197df54c2f9SSascha Wildner }
198df54c2f9SSascha Wildner 
199df54c2f9SSascha Wildner 
200df54c2f9SSascha Wildner 
201df54c2f9SSascha Wildner /*
202df54c2f9SSascha Wildner  * Function name:	tw_osli_execute_scsi
203df54c2f9SSascha Wildner  * Description:		Build a fw cmd, based on a CAM style ccb, and
204df54c2f9SSascha Wildner  *			send it down.
205df54c2f9SSascha Wildner  *
206df54c2f9SSascha Wildner  * Input:		req	-- ptr to OSL internal request context
207df54c2f9SSascha Wildner  *			ccb	-- ptr to CAM style ccb
208df54c2f9SSascha Wildner  * Output:		None
209df54c2f9SSascha Wildner  * Return value:	0	-- success
210df54c2f9SSascha Wildner  *			non-zero-- failure
211df54c2f9SSascha Wildner  */
212df54c2f9SSascha Wildner TW_INT32
213df54c2f9SSascha Wildner tw_osli_execute_scsi(struct tw_osli_req_context *req, union ccb *ccb)
214df54c2f9SSascha Wildner {
215df54c2f9SSascha Wildner 	struct twa_softc		*sc = req->ctlr;
216df54c2f9SSascha Wildner 	struct tw_cl_req_packet		*req_pkt;
217df54c2f9SSascha Wildner 	struct tw_cl_scsi_req_packet	*scsi_req;
218df54c2f9SSascha Wildner 	struct ccb_hdr			*ccb_h = &(ccb->ccb_h);
219df54c2f9SSascha Wildner 	struct ccb_scsiio		*csio = &(ccb->csio);
220df54c2f9SSascha Wildner 	TW_INT32			error;
221df54c2f9SSascha Wildner 
222df54c2f9SSascha Wildner 	tw_osli_dbg_dprintf(10, sc, "SCSI I/O request 0x%x",
223df54c2f9SSascha Wildner 		csio->cdb_io.cdb_bytes[0]);
224df54c2f9SSascha Wildner 
225df54c2f9SSascha Wildner 	if (ccb_h->target_id >= TW_CL_MAX_NUM_UNITS) {
226df54c2f9SSascha Wildner 		tw_osli_dbg_dprintf(3, sc, "Invalid target. PTL = %x %x %x",
227df54c2f9SSascha Wildner 			ccb_h->path_id, ccb_h->target_id, ccb_h->target_lun);
228df54c2f9SSascha Wildner 		ccb_h->status |= CAM_TID_INVALID;
229df54c2f9SSascha Wildner 		xpt_done(ccb);
230df54c2f9SSascha Wildner 		return(1);
231df54c2f9SSascha Wildner 	}
232df54c2f9SSascha Wildner 	if (ccb_h->target_lun >= TW_CL_MAX_NUM_LUNS) {
233df54c2f9SSascha Wildner 		tw_osli_dbg_dprintf(3, sc, "Invalid lun. PTL = %x %x %x",
234df54c2f9SSascha Wildner 			ccb_h->path_id, ccb_h->target_id, ccb_h->target_lun);
235df54c2f9SSascha Wildner 		ccb_h->status |= CAM_LUN_INVALID;
236df54c2f9SSascha Wildner 		xpt_done(ccb);
237df54c2f9SSascha Wildner 		return(1);
238df54c2f9SSascha Wildner 	}
239df54c2f9SSascha Wildner 
240df54c2f9SSascha Wildner 	if(ccb_h->flags & CAM_CDB_PHYS) {
241df54c2f9SSascha Wildner 		tw_osli_printf(sc, "",
242df54c2f9SSascha Wildner 			TW_CL_SEVERITY_ERROR_STRING,
243df54c2f9SSascha Wildner 			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
244df54c2f9SSascha Wildner 			0x2105,
245df54c2f9SSascha Wildner 			"Physical CDB address!");
246df54c2f9SSascha Wildner 		ccb_h->status = CAM_REQ_INVALID;
247df54c2f9SSascha Wildner 		xpt_done(ccb);
248df54c2f9SSascha Wildner 		return(1);
249df54c2f9SSascha Wildner 	}
250df54c2f9SSascha Wildner 
251df54c2f9SSascha Wildner 	/*
252df54c2f9SSascha Wildner 	 * We are going to work on this request.  Mark it as enqueued (though
253df54c2f9SSascha Wildner 	 * we don't actually queue it...)
254df54c2f9SSascha Wildner 	 */
255df54c2f9SSascha Wildner 	ccb_h->status |= CAM_SIM_QUEUED;
256df54c2f9SSascha Wildner 
257df54c2f9SSascha Wildner 	if((ccb_h->flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
258df54c2f9SSascha Wildner 		if(ccb_h->flags & CAM_DIR_IN)
259df54c2f9SSascha Wildner 			req->flags |= TW_OSLI_REQ_FLAGS_DATA_IN;
260df54c2f9SSascha Wildner 		else
261df54c2f9SSascha Wildner 			req->flags |= TW_OSLI_REQ_FLAGS_DATA_OUT;
262df54c2f9SSascha Wildner 	}
263df54c2f9SSascha Wildner 
264df54c2f9SSascha Wildner 	/* Build the CL understood request packet for SCSI cmds. */
265df54c2f9SSascha Wildner 	req_pkt = &req->req_pkt;
266df54c2f9SSascha Wildner 	req_pkt->status = 0;
267df54c2f9SSascha Wildner 	req_pkt->tw_osl_callback = tw_osl_complete_io;
268df54c2f9SSascha Wildner 	scsi_req = &(req_pkt->gen_req_pkt.scsi_req);
269df54c2f9SSascha Wildner 	scsi_req->unit = ccb_h->target_id;
270df54c2f9SSascha Wildner 	scsi_req->lun = ccb_h->target_lun;
271df54c2f9SSascha Wildner 	scsi_req->sense_len = 0;
272df54c2f9SSascha Wildner 	scsi_req->sense_data = (TW_UINT8 *)(&csio->sense_data);
273df54c2f9SSascha Wildner 	scsi_req->scsi_status = 0;
274df54c2f9SSascha Wildner 	if(ccb_h->flags & CAM_CDB_POINTER)
275df54c2f9SSascha Wildner 		scsi_req->cdb = csio->cdb_io.cdb_ptr;
276df54c2f9SSascha Wildner 	else
277df54c2f9SSascha Wildner 		scsi_req->cdb = csio->cdb_io.cdb_bytes;
278df54c2f9SSascha Wildner 	scsi_req->cdb_len = csio->cdb_len;
279df54c2f9SSascha Wildner 
280df54c2f9SSascha Wildner 	if (!(ccb_h->flags & CAM_DATA_PHYS)) {
281df54c2f9SSascha Wildner 		/* Virtual data addresses.  Need to convert them... */
282df54c2f9SSascha Wildner 		tw_osli_dbg_dprintf(3, sc,
283df54c2f9SSascha Wildner 			"XPT_SCSI_IO: Single virtual address!");
284df54c2f9SSascha Wildner 		if (!(ccb_h->flags & CAM_SCATTER_VALID)) {
285df54c2f9SSascha Wildner 			if (csio->dxfer_len > TW_CL_MAX_IO_SIZE) {
286df54c2f9SSascha Wildner 				tw_osli_printf(sc, "size = %d",
287df54c2f9SSascha Wildner 					TW_CL_SEVERITY_ERROR_STRING,
288df54c2f9SSascha Wildner 					TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
289df54c2f9SSascha Wildner 					0x2106,
290df54c2f9SSascha Wildner 					"I/O size too big",
291df54c2f9SSascha Wildner 					csio->dxfer_len);
292df54c2f9SSascha Wildner 				ccb_h->status = CAM_REQ_TOO_BIG;
2934fbf05f9SSascha Wildner 				ccb_h->status &= ~CAM_SIM_QUEUED;
294df54c2f9SSascha Wildner 				xpt_done(ccb);
295df54c2f9SSascha Wildner 				return(1);
296df54c2f9SSascha Wildner 			}
297df54c2f9SSascha Wildner 
298df54c2f9SSascha Wildner 			if ((req->length = csio->dxfer_len)) {
299df54c2f9SSascha Wildner 				req->data = csio->data_ptr;
300df54c2f9SSascha Wildner 				scsi_req->sgl_entries = 1;
301df54c2f9SSascha Wildner 			}
302df54c2f9SSascha Wildner 		} else {
303df54c2f9SSascha Wildner 			tw_osli_printf(sc, "",
304df54c2f9SSascha Wildner 				TW_CL_SEVERITY_ERROR_STRING,
305df54c2f9SSascha Wildner 				TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
306df54c2f9SSascha Wildner 				0x2107,
307df54c2f9SSascha Wildner 				"XPT_SCSI_IO: Got SGList");
308df54c2f9SSascha Wildner 			ccb_h->status = CAM_REQ_INVALID;
3094fbf05f9SSascha Wildner 			ccb_h->status &= ~CAM_SIM_QUEUED;
310df54c2f9SSascha Wildner 			xpt_done(ccb);
311df54c2f9SSascha Wildner 			return(1);
312df54c2f9SSascha Wildner 		}
313df54c2f9SSascha Wildner 	} else {
314df54c2f9SSascha Wildner 		/* Data addresses are physical. */
315df54c2f9SSascha Wildner 		tw_osli_printf(sc, "",
316df54c2f9SSascha Wildner 			TW_CL_SEVERITY_ERROR_STRING,
317df54c2f9SSascha Wildner 			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
318df54c2f9SSascha Wildner 			0x2108,
319df54c2f9SSascha Wildner 			"XPT_SCSI_IO: Physical data addresses");
320df54c2f9SSascha Wildner 		ccb_h->status = CAM_REQ_INVALID;
321df54c2f9SSascha Wildner 		ccb_h->status &= ~CAM_SIM_QUEUED;
322df54c2f9SSascha Wildner 		xpt_done(ccb);
323df54c2f9SSascha Wildner 		return(1);
324df54c2f9SSascha Wildner 	}
325df54c2f9SSascha Wildner 
3264fbf05f9SSascha Wildner 	req->deadline = tw_osl_get_local_time() + (ccb_h->timeout / 1000);
3274fbf05f9SSascha Wildner 
3284fbf05f9SSascha Wildner 
329df54c2f9SSascha Wildner 	/*
330df54c2f9SSascha Wildner 	 * twa_map_load_data_callback will fill in the SGL,
331df54c2f9SSascha Wildner 	 * and submit the I/O.
332df54c2f9SSascha Wildner 	 */
333df54c2f9SSascha Wildner 	error = tw_osli_map_request(req);
3344fbf05f9SSascha Wildner 	if ((error) && (req->flags & TW_OSLI_REQ_FLAGS_FAILED)) {
3354fbf05f9SSascha Wildner 		req->deadline = 0;
3364fbf05f9SSascha Wildner 		ccb_h->status = CAM_REQ_CMP_ERR;
3374fbf05f9SSascha Wildner 		ccb_h->status &= ~CAM_SIM_QUEUED;
3384fbf05f9SSascha Wildner 		xpt_done(ccb);
3394fbf05f9SSascha Wildner 	}
340df54c2f9SSascha Wildner 	return(error);
341df54c2f9SSascha Wildner }
342df54c2f9SSascha Wildner 
343df54c2f9SSascha Wildner 
344df54c2f9SSascha Wildner 
345df54c2f9SSascha Wildner /*
346df54c2f9SSascha Wildner  * Function name:	twa_action
347df54c2f9SSascha Wildner  * Description:		Driver entry point for CAM's use.
348df54c2f9SSascha Wildner  *
349df54c2f9SSascha Wildner  * Input:		sim	-- sim corresponding to the ctlr
350df54c2f9SSascha Wildner  *			ccb	-- ptr to CAM request
351df54c2f9SSascha Wildner  * Output:		None
352df54c2f9SSascha Wildner  * Return value:	None
353df54c2f9SSascha Wildner  */
354df54c2f9SSascha Wildner TW_VOID
355df54c2f9SSascha Wildner twa_action(struct cam_sim *sim, union ccb *ccb)
356df54c2f9SSascha Wildner {
357df54c2f9SSascha Wildner 	struct twa_softc	*sc = (struct twa_softc *)cam_sim_softc(sim);
358df54c2f9SSascha Wildner 	struct ccb_hdr		*ccb_h = &(ccb->ccb_h);
359df54c2f9SSascha Wildner 
360df54c2f9SSascha Wildner 	switch (ccb_h->func_code) {
361df54c2f9SSascha Wildner 	case XPT_SCSI_IO:	/* SCSI I/O */
362df54c2f9SSascha Wildner 	{
363df54c2f9SSascha Wildner 		struct tw_osli_req_context	*req;
364df54c2f9SSascha Wildner 
365df54c2f9SSascha Wildner 		req = tw_osli_get_request(sc);
366df54c2f9SSascha Wildner 		if (req == NULL) {
367df54c2f9SSascha Wildner 			tw_osli_dbg_dprintf(2, sc, "Cannot get request pkt.");
368df54c2f9SSascha Wildner 			/*
369df54c2f9SSascha Wildner 			 * Freeze the simq to maintain ccb ordering.  The next
370df54c2f9SSascha Wildner 			 * ccb that gets completed will unfreeze the simq.
371df54c2f9SSascha Wildner 			 */
3724fbf05f9SSascha Wildner 			ccb_h->status &= ~CAM_SIM_QUEUED;
373df54c2f9SSascha Wildner 			ccb_h->status |= CAM_REQUEUE_REQ;
374df54c2f9SSascha Wildner 			xpt_done(ccb);
375df54c2f9SSascha Wildner 			break;
376df54c2f9SSascha Wildner 		}
3774fbf05f9SSascha Wildner 
3784fbf05f9SSascha Wildner 		if ((tw_cl_is_reset_needed(&(req->ctlr->ctlr_handle)))) {
3794fbf05f9SSascha Wildner 			ccb_h->status &= ~CAM_SIM_QUEUED;
3804fbf05f9SSascha Wildner 			ccb_h->status |= CAM_REQUEUE_REQ;
3814fbf05f9SSascha Wildner 			xpt_done(ccb);
3824fbf05f9SSascha Wildner 			tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q);
3834fbf05f9SSascha Wildner 			break;
3844fbf05f9SSascha Wildner 		}
3854fbf05f9SSascha Wildner 
386df54c2f9SSascha Wildner 		req->req_handle.osl_req_ctxt = req;
387df54c2f9SSascha Wildner 		req->req_handle.is_io = TW_CL_TRUE;
388df54c2f9SSascha Wildner 		req->orig_req = ccb;
389df54c2f9SSascha Wildner 		if (tw_osli_execute_scsi(req, ccb))
390df54c2f9SSascha Wildner 			tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q);
391df54c2f9SSascha Wildner 		break;
392df54c2f9SSascha Wildner 	}
393df54c2f9SSascha Wildner 
394df54c2f9SSascha Wildner 	case XPT_ABORT:
395df54c2f9SSascha Wildner 		tw_osli_dbg_dprintf(2, sc, "Abort request.");
396df54c2f9SSascha Wildner 		ccb_h->status = CAM_UA_ABORT;
397df54c2f9SSascha Wildner 		xpt_done(ccb);
398df54c2f9SSascha Wildner 		break;
399df54c2f9SSascha Wildner 
400df54c2f9SSascha Wildner 	case XPT_RESET_BUS:
4014fbf05f9SSascha Wildner 		tw_cl_create_event(&(sc->ctlr_handle), TW_CL_FALSE,
402df54c2f9SSascha Wildner 			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
403df54c2f9SSascha Wildner 			0x2108, 0x3, TW_CL_SEVERITY_INFO_STRING,
404df54c2f9SSascha Wildner 			"Received Reset Bus request from CAM",
405df54c2f9SSascha Wildner 			" ");
406df54c2f9SSascha Wildner 
4074fbf05f9SSascha Wildner 		tw_cl_set_reset_needed(&(sc->ctlr_handle));
408df54c2f9SSascha Wildner 		ccb_h->status = CAM_REQ_CMP;
409df54c2f9SSascha Wildner 		xpt_done(ccb);
410df54c2f9SSascha Wildner 		break;
411df54c2f9SSascha Wildner 
412df54c2f9SSascha Wildner 	case XPT_SET_TRAN_SETTINGS:
413df54c2f9SSascha Wildner 		tw_osli_dbg_dprintf(3, sc, "XPT_SET_TRAN_SETTINGS");
414df54c2f9SSascha Wildner 
415df54c2f9SSascha Wildner 		/*
416df54c2f9SSascha Wildner 		 * This command is not supported, since it's very specific
417df54c2f9SSascha Wildner 		 * to SCSI, and we are doing ATA.
418df54c2f9SSascha Wildner 		 */
419df54c2f9SSascha Wildner 		ccb_h->status = CAM_FUNC_NOTAVAIL;
420df54c2f9SSascha Wildner 		xpt_done(ccb);
421df54c2f9SSascha Wildner 		break;
422df54c2f9SSascha Wildner 
423df54c2f9SSascha Wildner 	case XPT_GET_TRAN_SETTINGS:
424df54c2f9SSascha Wildner 	{
425df54c2f9SSascha Wildner 		struct ccb_trans_settings	*cts = &ccb->cts;
426df54c2f9SSascha Wildner 		struct ccb_trans_settings_scsi *scsi =
427df54c2f9SSascha Wildner 		    &cts->proto_specific.scsi;
428df54c2f9SSascha Wildner 		struct ccb_trans_settings_spi *spi =
429df54c2f9SSascha Wildner 		    &cts->xport_specific.spi;
430df54c2f9SSascha Wildner 
431df54c2f9SSascha Wildner 		cts->protocol = PROTO_SCSI;
432df54c2f9SSascha Wildner 		cts->protocol_version = SCSI_REV_2;
433df54c2f9SSascha Wildner 		cts->transport = XPORT_SPI;
434df54c2f9SSascha Wildner 		cts->transport_version = 2;
435df54c2f9SSascha Wildner 
436df54c2f9SSascha Wildner 		spi->valid = CTS_SPI_VALID_DISC;
437df54c2f9SSascha Wildner 		spi->flags = CTS_SPI_FLAGS_DISC_ENB;
438df54c2f9SSascha Wildner 		scsi->valid = CTS_SCSI_VALID_TQ;
439df54c2f9SSascha Wildner 		scsi->flags = CTS_SCSI_FLAGS_TAG_ENB;
440df54c2f9SSascha Wildner 		tw_osli_dbg_dprintf(3, sc, "XPT_GET_TRAN_SETTINGS");
441df54c2f9SSascha Wildner 		ccb_h->status = CAM_REQ_CMP;
442df54c2f9SSascha Wildner 		xpt_done(ccb);
443df54c2f9SSascha Wildner 		break;
444df54c2f9SSascha Wildner 	}
445df54c2f9SSascha Wildner 
446df54c2f9SSascha Wildner 	case XPT_CALC_GEOMETRY:
447df54c2f9SSascha Wildner 		tw_osli_dbg_dprintf(3, sc, "XPT_CALC_GEOMETRY");
448df54c2f9SSascha Wildner 		cam_calc_geometry(&ccb->ccg, 1/* extended */);
449df54c2f9SSascha Wildner 		xpt_done(ccb);
450df54c2f9SSascha Wildner 		break;
451df54c2f9SSascha Wildner 
452df54c2f9SSascha Wildner 	case XPT_PATH_INQ:    /* Path inquiry -- get twa properties */
453df54c2f9SSascha Wildner 	{
454df54c2f9SSascha Wildner 		struct ccb_pathinq	*path_inq = &ccb->cpi;
455df54c2f9SSascha Wildner 
456df54c2f9SSascha Wildner 		tw_osli_dbg_dprintf(3, sc, "XPT_PATH_INQ request");
457df54c2f9SSascha Wildner 
458df54c2f9SSascha Wildner 		path_inq->version_num = 1;
459df54c2f9SSascha Wildner 		path_inq->hba_inquiry = 0;
460df54c2f9SSascha Wildner 		path_inq->target_sprt = 0;
461df54c2f9SSascha Wildner 		path_inq->hba_misc = 0;
462df54c2f9SSascha Wildner 		path_inq->hba_eng_cnt = 0;
463df54c2f9SSascha Wildner 		path_inq->max_target = TW_CL_MAX_NUM_UNITS;
464df54c2f9SSascha Wildner 		path_inq->max_lun = TW_CL_MAX_NUM_LUNS - 1;
465df54c2f9SSascha Wildner 		path_inq->unit_number = cam_sim_unit(sim);
466df54c2f9SSascha Wildner 		path_inq->bus_id = cam_sim_bus(sim);
467df54c2f9SSascha Wildner 		path_inq->initiator_id = TW_CL_MAX_NUM_UNITS;
468df54c2f9SSascha Wildner 		path_inq->base_transfer_speed = 100000;
469df54c2f9SSascha Wildner 		strncpy(path_inq->sim_vid, "FreeBSD", SIM_IDLEN);
470df54c2f9SSascha Wildner 		strncpy(path_inq->hba_vid, "3ware", HBA_IDLEN);
471df54c2f9SSascha Wildner 		strncpy(path_inq->dev_name, cam_sim_name(sim), DEV_IDLEN);
472df54c2f9SSascha Wildner                 path_inq->transport = XPORT_SPI;
473df54c2f9SSascha Wildner                 path_inq->transport_version = 2;
474df54c2f9SSascha Wildner                 path_inq->protocol = PROTO_SCSI;
475df54c2f9SSascha Wildner                 path_inq->protocol_version = SCSI_REV_2;
4764fbf05f9SSascha Wildner #if 0 /* XXX swildner */
4774fbf05f9SSascha Wildner                 path_inq->maxio = TW_CL_MAX_IO_SIZE;
4784fbf05f9SSascha Wildner #endif
479df54c2f9SSascha Wildner 		ccb_h->status = CAM_REQ_CMP;
480df54c2f9SSascha Wildner 		xpt_done(ccb);
481df54c2f9SSascha Wildner 		break;
482df54c2f9SSascha Wildner 	}
483df54c2f9SSascha Wildner 
484df54c2f9SSascha Wildner 	default:
485df54c2f9SSascha Wildner 		tw_osli_dbg_dprintf(3, sc, "func_code = %x", ccb_h->func_code);
486df54c2f9SSascha Wildner 		ccb_h->status = CAM_REQ_INVALID;
487df54c2f9SSascha Wildner 		xpt_done(ccb);
488df54c2f9SSascha Wildner 		break;
489df54c2f9SSascha Wildner 	}
490df54c2f9SSascha Wildner }
491df54c2f9SSascha Wildner 
492df54c2f9SSascha Wildner 
493df54c2f9SSascha Wildner 
494df54c2f9SSascha Wildner /*
495df54c2f9SSascha Wildner  * Function name:	twa_poll
496df54c2f9SSascha Wildner  * Description:		Driver entry point called when interrupts are not
497df54c2f9SSascha Wildner  *			available.
498df54c2f9SSascha Wildner  *
499df54c2f9SSascha Wildner  * Input:		sim	-- sim corresponding to the controller
500df54c2f9SSascha Wildner  * Output:		None
501df54c2f9SSascha Wildner  * Return value:	None
502df54c2f9SSascha Wildner  */
503df54c2f9SSascha Wildner TW_VOID
504df54c2f9SSascha Wildner twa_poll(struct cam_sim *sim)
505df54c2f9SSascha Wildner {
506df54c2f9SSascha Wildner 	struct twa_softc *sc = (struct twa_softc *)(cam_sim_softc(sim));
507df54c2f9SSascha Wildner 
508df54c2f9SSascha Wildner 	tw_osli_dbg_dprintf(3, sc, "entering; sc = %p", sc);
509df54c2f9SSascha Wildner 	tw_cl_interrupt(&(sc->ctlr_handle));
510df54c2f9SSascha Wildner 	tw_osli_dbg_dprintf(3, sc, "exiting; sc = %p", sc);
511df54c2f9SSascha Wildner }
512df54c2f9SSascha Wildner 
513df54c2f9SSascha Wildner 
514df54c2f9SSascha Wildner 
515df54c2f9SSascha Wildner /*
516df54c2f9SSascha Wildner  * Function name:	tw_osli_request_bus_scan
517df54c2f9SSascha Wildner  * Description:		Requests CAM for a scan of the bus.
518df54c2f9SSascha Wildner  *
519df54c2f9SSascha Wildner  * Input:		sc	-- ptr to per ctlr structure
520df54c2f9SSascha Wildner  * Output:		None
521df54c2f9SSascha Wildner  * Return value:	0	-- success
522df54c2f9SSascha Wildner  *			non-zero-- failure
523df54c2f9SSascha Wildner  */
524df54c2f9SSascha Wildner TW_INT32
525df54c2f9SSascha Wildner tw_osli_request_bus_scan(struct twa_softc *sc)
526df54c2f9SSascha Wildner {
527df54c2f9SSascha Wildner 	union ccb	*ccb;
528df54c2f9SSascha Wildner 
529df54c2f9SSascha Wildner 	tw_osli_dbg_dprintf(3, sc, "entering");
530df54c2f9SSascha Wildner 
531df54c2f9SSascha Wildner 	/* If we get here before sc->sim is initialized, return an error. */
532df54c2f9SSascha Wildner 	if (!(sc->sim))
533df54c2f9SSascha Wildner 		return(ENXIO);
534df54c2f9SSascha Wildner 	if ((ccb = xpt_alloc_ccb()) == NULL)
535df54c2f9SSascha Wildner 		return(ENOMEM);
536df54c2f9SSascha Wildner 	lockmgr(sc->sim_lock, LK_EXCLUSIVE);
537df54c2f9SSascha Wildner 	if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, cam_sim_path(sc->sim),
538df54c2f9SSascha Wildner 	    CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
539df54c2f9SSascha Wildner 		xpt_free_ccb(ccb);
540df54c2f9SSascha Wildner 		lockmgr(sc->sim_lock, LK_RELEASE);
541df54c2f9SSascha Wildner 		return(EIO);
542df54c2f9SSascha Wildner 	}
543df54c2f9SSascha Wildner 
544df54c2f9SSascha Wildner 	xpt_setup_ccb(&ccb->ccb_h, ccb->ccb_h.path, 5/*priority (low)*/);
545df54c2f9SSascha Wildner 	ccb->ccb_h.func_code = XPT_SCAN_BUS;
546df54c2f9SSascha Wildner 	ccb->ccb_h.cbfcnp = twa_bus_scan_cb;
547df54c2f9SSascha Wildner 	ccb->crcn.flags = CAM_FLAG_NONE;
548df54c2f9SSascha Wildner 	xpt_action(ccb);
549df54c2f9SSascha Wildner 
550df54c2f9SSascha Wildner 	lockmgr(sc->sim_lock, LK_RELEASE);
551df54c2f9SSascha Wildner 	return(0);
552df54c2f9SSascha Wildner }
553df54c2f9SSascha Wildner 
554df54c2f9SSascha Wildner 
555df54c2f9SSascha Wildner 
556df54c2f9SSascha Wildner /*
557df54c2f9SSascha Wildner  * Function name:	twa_bus_scan_cb
558df54c2f9SSascha Wildner  * Description:		Callback from CAM on a bus scan request.
559df54c2f9SSascha Wildner  *
560df54c2f9SSascha Wildner  * Input:		periph	-- we don't use this
561df54c2f9SSascha Wildner  *			ccb	-- bus scan request ccb that we sent to CAM
562df54c2f9SSascha Wildner  * Output:		None
563df54c2f9SSascha Wildner  * Return value:	None
564df54c2f9SSascha Wildner  */
565df54c2f9SSascha Wildner static TW_VOID
566df54c2f9SSascha Wildner twa_bus_scan_cb(struct cam_periph *periph, union ccb *ccb)
567df54c2f9SSascha Wildner {
568df54c2f9SSascha Wildner 	tw_osli_dbg_printf(3, "entering");
569df54c2f9SSascha Wildner 
570df54c2f9SSascha Wildner 	if (ccb->ccb_h.status != CAM_REQ_CMP)
571df54c2f9SSascha Wildner 		kprintf("cam_scan_callback: failure status = %x\n",
572df54c2f9SSascha Wildner 			ccb->ccb_h.status);
573df54c2f9SSascha Wildner 	else
574df54c2f9SSascha Wildner 		tw_osli_dbg_printf(3, "success");
575df54c2f9SSascha Wildner 
576df54c2f9SSascha Wildner 	xpt_free_path(ccb->ccb_h.path);
577df54c2f9SSascha Wildner 	kfree(ccb, M_TEMP);
578df54c2f9SSascha Wildner }
579df54c2f9SSascha Wildner 
580df54c2f9SSascha Wildner 
581df54c2f9SSascha Wildner 
582df54c2f9SSascha Wildner /*
583df54c2f9SSascha Wildner  * Function name:	tw_osli_disallow_new_requests
584df54c2f9SSascha Wildner  * Description:		Calls the appropriate CAM function, so as to freeze
585df54c2f9SSascha Wildner  *			the flow of new requests from CAM to this controller.
586df54c2f9SSascha Wildner  *
587df54c2f9SSascha Wildner  * Input:		sc	-- ptr to OSL internal ctlr context
588df54c2f9SSascha Wildner  *			req_handle -- ptr to request handle sent by OSL.
589df54c2f9SSascha Wildner  * Output:		None
590df54c2f9SSascha Wildner  * Return value:	None
591df54c2f9SSascha Wildner  */
592df54c2f9SSascha Wildner TW_VOID
593df54c2f9SSascha Wildner tw_osli_disallow_new_requests(struct twa_softc *sc,
594df54c2f9SSascha Wildner 	struct tw_cl_req_handle *req_handle)
595df54c2f9SSascha Wildner {
596df54c2f9SSascha Wildner 	/* Only freeze/release the simq for IOs */
597df54c2f9SSascha Wildner 	if (req_handle->is_io) {
598df54c2f9SSascha Wildner 		struct tw_osli_req_context	*req = req_handle->osl_req_ctxt;
599df54c2f9SSascha Wildner 		union ccb			*ccb = (union ccb *)(req->orig_req);
600df54c2f9SSascha Wildner 
601df54c2f9SSascha Wildner 		xpt_freeze_simq(sc->sim, 1);
602df54c2f9SSascha Wildner 		ccb->ccb_h.status |= CAM_RELEASE_SIMQ;
603df54c2f9SSascha Wildner 	}
604df54c2f9SSascha Wildner }
605df54c2f9SSascha Wildner 
606df54c2f9SSascha Wildner 
607df54c2f9SSascha Wildner 
608df54c2f9SSascha Wildner /*
6094fbf05f9SSascha Wildner  * Function name:	tw_osl_timeout
6104fbf05f9SSascha Wildner  * Description:		Call to timeout().
611df54c2f9SSascha Wildner  *
6124fbf05f9SSascha Wildner  * Input:		req_handle -- ptr to request handle sent by OSL.
613df54c2f9SSascha Wildner  * Output:		None
614df54c2f9SSascha Wildner  * Return value:	None
615df54c2f9SSascha Wildner  */
616df54c2f9SSascha Wildner TW_VOID
6174fbf05f9SSascha Wildner tw_osl_timeout(struct tw_cl_req_handle *req_handle)
618df54c2f9SSascha Wildner {
6194fbf05f9SSascha Wildner 	struct tw_osli_req_context	*req = req_handle->osl_req_ctxt;
6204fbf05f9SSascha Wildner 	union ccb			*ccb = (union ccb *)(req->orig_req);
6214fbf05f9SSascha Wildner 	struct ccb_hdr			*ccb_h = &(ccb->ccb_h);
6224fbf05f9SSascha Wildner 
6234fbf05f9SSascha Wildner 	req->deadline = tw_osl_get_local_time() + (ccb_h->timeout / 1000);
6244fbf05f9SSascha Wildner }
6254fbf05f9SSascha Wildner 
6264fbf05f9SSascha Wildner 
6274fbf05f9SSascha Wildner 
6284fbf05f9SSascha Wildner /*
6294fbf05f9SSascha Wildner  * Function name:	tw_osl_untimeout
6304fbf05f9SSascha Wildner  * Description:		Inverse of call to timeout().
6314fbf05f9SSascha Wildner  *
6324fbf05f9SSascha Wildner  * Input:		req_handle -- ptr to request handle sent by OSL.
6334fbf05f9SSascha Wildner  * Output:		None
6344fbf05f9SSascha Wildner  * Return value:	None
6354fbf05f9SSascha Wildner  */
6364fbf05f9SSascha Wildner TW_VOID
6374fbf05f9SSascha Wildner tw_osl_untimeout(struct tw_cl_req_handle *req_handle)
6384fbf05f9SSascha Wildner {
6394fbf05f9SSascha Wildner 	struct tw_osli_req_context	*req = req_handle->osl_req_ctxt;
6404fbf05f9SSascha Wildner 
6414fbf05f9SSascha Wildner 	req->deadline = 0;
642df54c2f9SSascha Wildner }
643df54c2f9SSascha Wildner 
644df54c2f9SSascha Wildner 
645df54c2f9SSascha Wildner 
646df54c2f9SSascha Wildner /*
647df54c2f9SSascha Wildner  * Function name:	tw_osl_scan_bus
648df54c2f9SSascha Wildner  * Description:		CL calls this function to request for a bus scan.
649df54c2f9SSascha Wildner  *
650df54c2f9SSascha Wildner  * Input:		ctlr_handle	-- ptr to controller handle
651df54c2f9SSascha Wildner  * Output:		None
652df54c2f9SSascha Wildner  * Return value:	None
653df54c2f9SSascha Wildner  */
654df54c2f9SSascha Wildner TW_VOID
655df54c2f9SSascha Wildner tw_osl_scan_bus(struct tw_cl_ctlr_handle *ctlr_handle)
656df54c2f9SSascha Wildner {
657df54c2f9SSascha Wildner 	struct twa_softc	*sc = ctlr_handle->osl_ctlr_ctxt;
658df54c2f9SSascha Wildner 	TW_INT32		error;
659df54c2f9SSascha Wildner 
660df54c2f9SSascha Wildner 	if ((error = tw_osli_request_bus_scan(sc)))
661df54c2f9SSascha Wildner 		tw_osli_printf(sc, "error = %d",
662df54c2f9SSascha Wildner 			TW_CL_SEVERITY_ERROR_STRING,
663df54c2f9SSascha Wildner 			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
664df54c2f9SSascha Wildner 			0x2109,
665df54c2f9SSascha Wildner 			"Bus scan request to CAM failed",
666df54c2f9SSascha Wildner 			error);
667df54c2f9SSascha Wildner }
668df54c2f9SSascha Wildner 
669df54c2f9SSascha Wildner 
670df54c2f9SSascha Wildner 
671df54c2f9SSascha Wildner /*
672df54c2f9SSascha Wildner  * Function name:	tw_osl_complete_io
673df54c2f9SSascha Wildner  * Description:		Called to complete CAM scsi requests.
674df54c2f9SSascha Wildner  *
675df54c2f9SSascha Wildner  * Input:		req_handle	-- ptr to request handle
676df54c2f9SSascha Wildner  * Output:		None
677df54c2f9SSascha Wildner  * Return value:	None
678df54c2f9SSascha Wildner  */
679df54c2f9SSascha Wildner TW_VOID
680df54c2f9SSascha Wildner tw_osl_complete_io(struct tw_cl_req_handle *req_handle)
681df54c2f9SSascha Wildner {
682df54c2f9SSascha Wildner 	struct tw_osli_req_context	*req = req_handle->osl_req_ctxt;
683df54c2f9SSascha Wildner 	struct tw_cl_req_packet		*req_pkt =
684df54c2f9SSascha Wildner 		(struct tw_cl_req_packet *)(&req->req_pkt);
685df54c2f9SSascha Wildner 	struct tw_cl_scsi_req_packet	*scsi_req;
686df54c2f9SSascha Wildner 	struct twa_softc		*sc = req->ctlr;
687df54c2f9SSascha Wildner 	union ccb			*ccb = (union ccb *)(req->orig_req);
688df54c2f9SSascha Wildner 
689df54c2f9SSascha Wildner 	tw_osli_dbg_dprintf(10, sc, "entering");
690df54c2f9SSascha Wildner 
691df54c2f9SSascha Wildner 	if (req->state != TW_OSLI_REQ_STATE_BUSY)
692df54c2f9SSascha Wildner 		tw_osli_printf(sc, "request = %p, status = %d",
693df54c2f9SSascha Wildner 			TW_CL_SEVERITY_ERROR_STRING,
694df54c2f9SSascha Wildner 			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
695df54c2f9SSascha Wildner 			0x210A,
696df54c2f9SSascha Wildner 			"Unposted command completed!!",
697df54c2f9SSascha Wildner 			req, req->state);
698df54c2f9SSascha Wildner 
699df54c2f9SSascha Wildner 	/*
700df54c2f9SSascha Wildner 	 * Remove request from the busy queue.  Just mark it complete.
701df54c2f9SSascha Wildner 	 * There's no need to move it into the complete queue as we are
702df54c2f9SSascha Wildner 	 * going to be done with it right now.
703df54c2f9SSascha Wildner 	 */
704df54c2f9SSascha Wildner 	req->state = TW_OSLI_REQ_STATE_COMPLETE;
705df54c2f9SSascha Wildner 	tw_osli_req_q_remove_item(req, TW_OSLI_BUSY_Q);
706df54c2f9SSascha Wildner 
707df54c2f9SSascha Wildner 	tw_osli_unmap_request(req);
708df54c2f9SSascha Wildner 
7094fbf05f9SSascha Wildner 	req->deadline = 0;
710df54c2f9SSascha Wildner 	if (req->error_code) {
711df54c2f9SSascha Wildner 		/* This request never got submitted to the firmware. */
712df54c2f9SSascha Wildner 		if (req->error_code == EBUSY) {
713df54c2f9SSascha Wildner 			/*
714df54c2f9SSascha Wildner 			 * Cmd queue is full, or the Common Layer is out of
715df54c2f9SSascha Wildner 			 * resources.  The simq will already have been frozen.
716df54c2f9SSascha Wildner 			 * When this ccb gets completed will unfreeze the simq.
717df54c2f9SSascha Wildner 			 */
718df54c2f9SSascha Wildner 			ccb->ccb_h.status |= CAM_REQUEUE_REQ;
719df54c2f9SSascha Wildner 		}
720df54c2f9SSascha Wildner 		else if (req->error_code == EFBIG)
721df54c2f9SSascha Wildner 			ccb->ccb_h.status = CAM_REQ_TOO_BIG;
722df54c2f9SSascha Wildner 		else
723df54c2f9SSascha Wildner 			ccb->ccb_h.status = CAM_REQ_CMP_ERR;
724df54c2f9SSascha Wildner 	} else {
725df54c2f9SSascha Wildner 		scsi_req = &(req_pkt->gen_req_pkt.scsi_req);
726df54c2f9SSascha Wildner 		if (req_pkt->status == TW_CL_ERR_REQ_SUCCESS)
727df54c2f9SSascha Wildner 			ccb->ccb_h.status = CAM_REQ_CMP;
728df54c2f9SSascha Wildner 		else {
729df54c2f9SSascha Wildner 			if (req_pkt->status & TW_CL_ERR_REQ_INVALID_TARGET)
73085b59853SSascha Wildner 				ccb->ccb_h.status |= CAM_SEL_TIMEOUT;
731df54c2f9SSascha Wildner 			else if (req_pkt->status & TW_CL_ERR_REQ_INVALID_LUN)
73285b59853SSascha Wildner 				ccb->ccb_h.status |= CAM_DEV_NOT_THERE;
733df54c2f9SSascha Wildner 			else if (req_pkt->status & TW_CL_ERR_REQ_SCSI_ERROR)
734df54c2f9SSascha Wildner 				ccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
735df54c2f9SSascha Wildner 			else if (req_pkt->status & TW_CL_ERR_REQ_BUS_RESET)
7364fbf05f9SSascha Wildner 				ccb->ccb_h.status |= (CAM_REQUEUE_REQ | CAM_SCSI_BUS_RESET);
737df54c2f9SSascha Wildner 			/*
738df54c2f9SSascha Wildner 			 * If none of the above errors occurred, simply
739df54c2f9SSascha Wildner 			 * mark completion error.
740df54c2f9SSascha Wildner 			 */
741df54c2f9SSascha Wildner 			if (ccb->ccb_h.status == 0)
742df54c2f9SSascha Wildner 				ccb->ccb_h.status = CAM_REQ_CMP_ERR;
743df54c2f9SSascha Wildner 
744df54c2f9SSascha Wildner 			if (req_pkt->status & TW_CL_ERR_REQ_AUTO_SENSE_VALID) {
745df54c2f9SSascha Wildner 				ccb->csio.sense_len = scsi_req->sense_len;
746df54c2f9SSascha Wildner 				ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
747df54c2f9SSascha Wildner 			}
748df54c2f9SSascha Wildner 		}
749df54c2f9SSascha Wildner 
750df54c2f9SSascha Wildner 		ccb->csio.scsi_status = scsi_req->scsi_status;
751df54c2f9SSascha Wildner 	}
752df54c2f9SSascha Wildner 
753df54c2f9SSascha Wildner 	ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
754df54c2f9SSascha Wildner 	lockmgr(sc->sim_lock, LK_EXCLUSIVE);
755df54c2f9SSascha Wildner 	xpt_done(ccb);
756df54c2f9SSascha Wildner 	lockmgr(sc->sim_lock, LK_RELEASE);
757df54c2f9SSascha Wildner 	if (! req->error_code)
758df54c2f9SSascha Wildner 		 /* twa_action will free the request otherwise */
759df54c2f9SSascha Wildner 		tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q);
760df54c2f9SSascha Wildner }
761