tw_osl_cam.c revision 172496
10SN/A/*
22362SN/A * Copyright (c) 2004-07 Applied Micro Circuits Corporation.
30SN/A * Copyright (c) 2004-05 Vinod Kashyap.
40SN/A * All rights reserved.
50SN/A *
60SN/A * Redistribution and use in source and binary forms, with or without
72362SN/A * modification, are permitted provided that the following conditions
80SN/A * are met:
92362SN/A * 1. Redistributions of source code must retain the above copyright
100SN/A *    notice, this list of conditions and the following disclaimer.
110SN/A * 2. Redistributions in binary form must reproduce the above copyright
120SN/A *    notice, this list of conditions and the following disclaimer in the
130SN/A *    documentation and/or other materials provided with the distribution.
140SN/A *
150SN/A * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
160SN/A * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
170SN/A * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
180SN/A * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
190SN/A * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
200SN/A * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
212362SN/A * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
222362SN/A * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
232362SN/A * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
240SN/A * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
250SN/A * SUCH DAMAGE.
260SN/A *
270SN/A *	$FreeBSD: head/sys/dev/twa/tw_osl_cam.c 172496 2007-10-09 17:43:57Z scottl $
280SN/A */
290SN/A
300SN/A/*
310SN/A * AMCC'S 3ware driver for 9000 series storage controllers.
320SN/A *
330SN/A * Author: Vinod Kashyap
340SN/A * Modifications by: Adam Radford
350SN/A * Modifications by: Manjunath Ranganathaiah
360SN/A */
370SN/A
380SN/A
390SN/A/*
400SN/A * FreeBSD CAM related functions.
4113344Sredestad */
420SN/A
430SN/A
4413344Sredestad#include <dev/twa/tw_osl_includes.h>
450SN/A
460SN/A#include <cam/cam.h>
470SN/A#include <cam/cam_ccb.h>
480SN/A#include <cam/cam_sim.h>
490SN/A#include <cam/cam_xpt_sim.h>
500SN/A#include <cam/cam_debug.h>
510SN/A#include <cam/cam_periph.h>
520SN/A
530SN/A#include <cam/scsi/scsi_all.h>
540SN/A#include <cam/scsi/scsi_message.h>
550SN/A
560SN/Astatic TW_VOID	twa_action(struct cam_sim *sim, union ccb *ccb);
570SN/Astatic TW_VOID	twa_poll(struct cam_sim *sim);
580SN/Astatic TW_VOID	twa_timeout(TW_VOID *arg);
590SN/Astatic TW_VOID	twa_bus_scan_cb(struct cam_periph *periph, union ccb *ccb);
600SN/A
610SN/Astatic TW_INT32	tw_osli_execute_scsi(struct tw_osli_req_context *req,
620SN/A	union ccb *ccb);
630SN/A
640SN/A
650SN/A
660SN/A/*
670SN/A * Function name:	tw_osli_cam_attach
680SN/A * Description:		Attaches the driver to CAM.
690SN/A *
700SN/A * Input:		sc	-- ptr to OSL internal ctlr context
710SN/A * Output:		None
720SN/A * Return value:	0	-- success
730SN/A *			non-zero-- failure
740SN/A */
750SN/ATW_INT32
760SN/Atw_osli_cam_attach(struct twa_softc *sc)
770SN/A{
780SN/A	struct cam_devq		*devq;
790SN/A	TW_INT32		error;
800SN/A
810SN/A	tw_osli_dbg_dprintf(3, sc, "entered");
820SN/A
830SN/A	/*
840SN/A	 * Create the device queue for our SIM.
850SN/A	 */
860SN/A	if ((devq = cam_simq_alloc(TW_OSLI_MAX_NUM_IOS)) == NULL) {
870SN/A		tw_osli_printf(sc, "error = %d",
880SN/A			TW_CL_SEVERITY_ERROR_STRING,
890SN/A			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
900SN/A			0x2100,
910SN/A			"Failed to create SIM device queue",
920SN/A			ENOMEM);
930SN/A		return(ENOMEM);
940SN/A	}
950SN/A
960SN/A	/*
970SN/A	 * Create a SIM entry.  Though we can support TW_OSLI_MAX_NUM_IOS
980SN/A	 * simultaneous requests, we claim to be able to handle only
990SN/A	 * (TW_OSLI_MAX_NUM_IOS - 1), so that we always have a request
1000SN/A	 * packet available to service ioctls.
1010SN/A	 */
1020SN/A	tw_osli_dbg_dprintf(3, sc, "Calling cam_sim_alloc");
1030SN/A	sc->sim = cam_sim_alloc(twa_action, twa_poll, "twa", sc,
1040SN/A			device_get_unit(sc->bus_dev), sc->sim_lock,
1050SN/A			TW_OSLI_MAX_NUM_IOS - 1, 1, devq);
1060SN/A	if (sc->sim == NULL) {
1070SN/A		cam_simq_free(devq);
1080SN/A		tw_osli_printf(sc, "error = %d",
1090SN/A			TW_CL_SEVERITY_ERROR_STRING,
1100SN/A			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
1110SN/A			0x2101,
1120SN/A			"Failed to create a SIM entry",
1130SN/A			ENOMEM);
1140SN/A		return(ENOMEM);
1150SN/A	}
1160SN/A
1170SN/A	/*
1180SN/A	 * Register the bus.
1190SN/A	 */
1200SN/A	tw_osli_dbg_dprintf(3, sc, "Calling xpt_bus_register");
1210SN/A	mtx_lock(sc->sim_lock);
1220SN/A	if (xpt_bus_register(sc->sim, sc->bus_dev, 0) != CAM_SUCCESS) {
1230SN/A		cam_sim_free(sc->sim, TRUE);
1240SN/A		sc->sim = NULL; /* so cam_detach will not try to free it */
1250SN/A		tw_osli_printf(sc, "error = %d",
1260SN/A			TW_CL_SEVERITY_ERROR_STRING,
1270SN/A			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
1280SN/A			0x2102,
1290SN/A			"Failed to register the bus",
1300SN/A			ENXIO);
1310SN/A		mtx_unlock(sc->sim_lock);
1320SN/A		return(ENXIO);
1330SN/A	}
1340SN/A
1350SN/A	tw_osli_dbg_dprintf(3, sc, "Calling xpt_create_path");
1360SN/A	if (xpt_create_path(&sc->path, NULL,
1370SN/A				cam_sim_path(sc->sim),
13813216Svtewari				CAM_TARGET_WILDCARD,
13913216Svtewari				CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
14013216Svtewari		xpt_bus_deregister(cam_sim_path (sc->sim));
14113216Svtewari		/* Passing TRUE to cam_sim_free will free the devq as well. */
14213216Svtewari		cam_sim_free(sc->sim, TRUE);
14313216Svtewari		tw_osli_printf(sc, "error = %d",
14413216Svtewari			TW_CL_SEVERITY_ERROR_STRING,
14513216Svtewari			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
14613216Svtewari			0x2103,
14713216Svtewari			"Failed to create path",
14813216Svtewari			ENXIO);
14913216Svtewari		mtx_unlock(sc->sim_lock);
1500SN/A		return(ENXIO);
1510SN/A	}
1520SN/A
1530SN/A	tw_osli_dbg_dprintf(3, sc, "Calling xpt_setup_ccb");
1540SN/A	mtx_unlock(sc->sim_lock);
1550SN/A
1560SN/A	tw_osli_dbg_dprintf(3, sc, "Calling tw_osli_request_bus_scan");
1570SN/A	/*
1580SN/A	 * Request a bus scan, so that CAM gets to know of
15913344Sredestad	 * the logical units that we control.
1600SN/A	 */
1610SN/A	if ((error = tw_osli_request_bus_scan(sc)))
16213344Sredestad		tw_osli_printf(sc, "error = %d",
1630SN/A			TW_CL_SEVERITY_ERROR_STRING,
1640SN/A			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
1650SN/A			0x2104,
1660SN/A			"Bus scan request to CAM failed",
16713344Sredestad			error);
1680SN/A
1690SN/A	tw_osli_dbg_dprintf(3, sc, "exiting");
1700SN/A	return(0);
1710SN/A}
1720SN/A
1730SN/A
1740SN/A
1750SN/A/*
1760SN/A * Function name:	tw_osli_cam_detach
1770SN/A * Description:		Detaches the driver from CAM.
1780SN/A *
1790SN/A * Input:		sc	-- ptr to OSL internal ctlr context
1800SN/A * Output:		None
1810SN/A * Return value:	None
1820SN/A */
1830SN/ATW_VOID
1840SN/Atw_osli_cam_detach(struct twa_softc *sc)
1850SN/A{
1860SN/A	tw_osli_dbg_dprintf(3, sc, "entered");
1870SN/A
1880SN/A#ifdef TW_OSLI_DEFERRED_INTR_USED
1890SN/A	/*  - drain the taskqueue
1900SN/A           Ctrl is already went down so, no more enqueuetask will
1910SN/A           happen . Don't  hold any locks, that task might need.
1920SN/A 	*/
1930SN/A
1940SN/A	taskqueue_drain(taskqueue_fast, &(sc->deferred_intr_callback));
1950SN/A#endif
1960SN/A	mtx_lock(sc->sim_lock);
1970SN/A
1980SN/A	if (sc->path)
1990SN/A		xpt_free_path(sc->path);
2000SN/A	if (sc->sim) {
2010SN/A		xpt_bus_deregister(cam_sim_path(sc->sim));
2020SN/A		/* Passing TRUE to cam_sim_free will free the devq as well. */
2030SN/A		cam_sim_free(sc->sim, TRUE);
2040SN/A	}
2050SN/A	/* It's ok have 1 hold count while destroying the mutex */
2060SN/A	mtx_destroy(sc->sim_lock);
2070SN/A}
2080SN/A
2090SN/A
2100SN/A
2110SN/A/*
2120SN/A * Function name:	tw_osli_execute_scsi
2130SN/A * Description:		Build a fw cmd, based on a CAM style ccb, and
2140SN/A *			send it down.
2150SN/A *
2160SN/A * Input:		req	-- ptr to OSL internal request context
2170SN/A *			ccb	-- ptr to CAM style ccb
2180SN/A * Output:		None
2190SN/A * Return value:	0	-- success
2200SN/A *			non-zero-- failure
2210SN/A */
2220SN/ATW_INT32
2230SN/Atw_osli_execute_scsi(struct tw_osli_req_context *req, union ccb *ccb)
2240SN/A{
2250SN/A	struct twa_softc		*sc = req->ctlr;
2260SN/A	struct tw_cl_req_packet		*req_pkt;
2270SN/A	struct tw_cl_scsi_req_packet	*scsi_req;
2280SN/A	struct ccb_hdr			*ccb_h = &(ccb->ccb_h);
2290SN/A	struct ccb_scsiio		*csio = &(ccb->csio);
2300SN/A	TW_INT32			error;
2310SN/A
2320SN/A	tw_osli_dbg_dprintf(10, sc, "SCSI I/O request 0x%x",
2330SN/A		csio->cdb_io.cdb_bytes[0]);
2340SN/A
2350SN/A	if (ccb_h->target_id >= TW_CL_MAX_NUM_UNITS) {
2360SN/A		tw_osli_dbg_dprintf(3, sc, "Invalid target. PTL = %x %x %x",
2370SN/A			ccb_h->path_id, ccb_h->target_id, ccb_h->target_lun);
2380SN/A		ccb_h->status |= CAM_TID_INVALID;
2390SN/A		xpt_done(ccb);
2400SN/A		return(1);
2410SN/A	}
2420SN/A	if (ccb_h->target_lun >= TW_CL_MAX_NUM_LUNS) {
2430SN/A		tw_osli_dbg_dprintf(3, sc, "Invalid lun. PTL = %x %x %x",
2440SN/A			ccb_h->path_id, ccb_h->target_id, ccb_h->target_lun);
2450SN/A		ccb_h->status |= CAM_LUN_INVALID;
2460SN/A		xpt_done(ccb);
2470SN/A		return(1);
2480SN/A	}
2490SN/A
2500SN/A	if(ccb_h->flags & CAM_CDB_PHYS) {
2510SN/A		tw_osli_printf(sc, "",
2520SN/A			TW_CL_SEVERITY_ERROR_STRING,
2530SN/A			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
2540SN/A			0x2105,
2550SN/A			"Physical CDB address!");
2560SN/A		ccb_h->status = CAM_REQ_CMP_ERR;
2570SN/A		xpt_done(ccb);
25811375Ssherman		return(1);
25911375Ssherman	}
26011375Ssherman
26111375Ssherman	/*
26211375Ssherman	 * We are going to work on this request.  Mark it as enqueued (though
2630SN/A	 * we don't actually queue it...)
2640SN/A	 */
2650SN/A	ccb_h->status |= CAM_SIM_QUEUED;
2660SN/A
2670SN/A	if((ccb_h->flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
2680SN/A		if(ccb_h->flags & CAM_DIR_IN)
2690SN/A			req->flags |= TW_OSLI_REQ_FLAGS_DATA_IN;
2700SN/A		else
2710SN/A			req->flags |= TW_OSLI_REQ_FLAGS_DATA_OUT;
2720SN/A	}
2730SN/A
2740SN/A	/* Build the CL understood request packet for SCSI cmds. */
2750SN/A	req_pkt = &req->req_pkt;
2760SN/A	req_pkt->status = 0;
2770SN/A	req_pkt->tw_osl_callback = tw_osl_complete_io;
2780SN/A	scsi_req = &(req_pkt->gen_req_pkt.scsi_req);
2790SN/A	scsi_req->unit = ccb_h->target_id;
2800SN/A	scsi_req->lun = ccb_h->target_lun;
28113216Svtewari	scsi_req->sense_len = 0;
28213216Svtewari	scsi_req->sense_data = (TW_UINT8 *)(&csio->sense_data);
2830SN/A	scsi_req->scsi_status = 0;
28413216Svtewari	if(ccb_h->flags & CAM_CDB_POINTER)
28513216Svtewari		scsi_req->cdb = csio->cdb_io.cdb_ptr;
28613216Svtewari	else
28713216Svtewari		scsi_req->cdb = csio->cdb_io.cdb_bytes;
28811375Ssherman	scsi_req->cdb_len = csio->cdb_len;
28913216Svtewari
2900SN/A	if (!(ccb_h->flags & CAM_DATA_PHYS)) {
2910SN/A		/* Virtual data addresses.  Need to convert them... */
29211375Ssherman		tw_osli_dbg_dprintf(3, sc,
29311375Ssherman			"XPT_SCSI_IO: Single virtual address!");
29411375Ssherman		if (!(ccb_h->flags & CAM_SCATTER_VALID)) {
29511375Ssherman			if (csio->dxfer_len > TW_CL_MAX_IO_SIZE) {
29611375Ssherman				tw_osli_printf(sc, "size = %d",
29711375Ssherman					TW_CL_SEVERITY_ERROR_STRING,
29811375Ssherman					TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
29911375Ssherman					0x2106,
3000SN/A					"I/O size too big",
30111375Ssherman					csio->dxfer_len);
30211375Ssherman				ccb_h->status = CAM_REQ_TOO_BIG;
30311375Ssherman				xpt_done(ccb);
30411375Ssherman				return(1);
30511375Ssherman			}
30611375Ssherman
3070SN/A			if ((req->length = csio->dxfer_len)) {
3080SN/A				req->data = csio->data_ptr;
3090SN/A				scsi_req->sgl_entries = 1;
3100SN/A			}
3110SN/A		} else {
3120SN/A			tw_osli_printf(sc, "",
3130SN/A				TW_CL_SEVERITY_ERROR_STRING,
3140SN/A				TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
3150SN/A				0x2107,
3160SN/A				"XPT_SCSI_IO: Got SGList");
3170SN/A			ccb_h->status = CAM_REQ_CMP_ERR;
3180SN/A			xpt_done(ccb);
3190SN/A			return(1);
3200SN/A		}
3210SN/A	} else {
3220SN/A		/* Data addresses are physical. */
3230SN/A		tw_osli_printf(sc, "",
3240SN/A			TW_CL_SEVERITY_ERROR_STRING,
3250SN/A			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
3260SN/A			0x2108,
3270SN/A			"XPT_SCSI_IO: Physical data addresses");
3280SN/A		ccb_h->status = CAM_REQ_CMP_ERR;
3290SN/A		ccb_h->status |= CAM_RELEASE_SIMQ;
3300SN/A		ccb_h->status &= ~CAM_SIM_QUEUED;
3310SN/A		xpt_done(ccb);
3320SN/A		return(1);
3330SN/A	}
3340SN/A
3350SN/A	ccb_h->timeout_ch = timeout(twa_timeout, req,
3360SN/A		(ccb_h->timeout * hz) / 1000);
3370SN/A	/*
3380SN/A	 * twa_map_load_data_callback will fill in the SGL,
3390SN/A	 * and submit the I/O.
3400SN/A	 */
3410SN/A	error = tw_osli_map_request(req);
3420SN/A	return(error);
3430SN/A}
3440SN/A
3450SN/A
3460SN/A
3470SN/A/*
3480SN/A * Function name:	twa_action
3490SN/A * Description:		Driver entry point for CAM's use.
3500SN/A *
3510SN/A * Input:		sim	-- sim corresponding to the ctlr
3520SN/A *			ccb	-- ptr to CAM request
3530SN/A * Output:		None
354 * Return value:	None
355 */
356TW_VOID
357twa_action(struct cam_sim *sim, union ccb *ccb)
358{
359	struct twa_softc	*sc = (struct twa_softc *)cam_sim_softc(sim);
360	struct ccb_hdr		*ccb_h = &(ccb->ccb_h);
361
362	switch (ccb_h->func_code) {
363	case XPT_SCSI_IO:	/* SCSI I/O */
364	{
365		struct tw_osli_req_context	*req;
366
367		if ((sc->state & TW_OSLI_CTLR_STATE_SIMQ_FROZEN) ||
368				((req = tw_osli_get_request(sc)) == NULL)) {
369			tw_osli_dbg_dprintf(2, sc,
370				"simq frozen/Cannot get request pkt.");
371			/*
372			 * Freeze the simq to maintain ccb ordering.  The next
373			 * ccb that gets completed will unfreeze the simq.
374			 */
375			tw_osli_disallow_new_requests(sc);
376			ccb_h->status |= CAM_REQUEUE_REQ;
377			xpt_done(ccb);
378			break;
379		}
380		req->req_handle.osl_req_ctxt = req;
381		req->orig_req = ccb;
382		if (tw_osli_execute_scsi(req, ccb))
383			tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q);
384		break;
385	}
386
387	case XPT_ABORT:
388		tw_osli_dbg_dprintf(2, sc, "Abort request.");
389		ccb_h->status = CAM_UA_ABORT;
390		xpt_done(ccb);
391		break;
392
393	case XPT_RESET_BUS:
394		tw_cl_create_event(&(sc->ctlr_handle), TW_CL_TRUE,
395			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
396			0x2108, 0x3, TW_CL_SEVERITY_INFO_STRING,
397			"Received Reset Bus request from CAM",
398			" ");
399
400		mtx_unlock(sc->sim_lock);
401		if (tw_cl_reset_ctlr(&sc->ctlr_handle)) {
402			tw_cl_create_event(&(sc->ctlr_handle), TW_CL_TRUE,
403				TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
404				0x2109, 0x1, TW_CL_SEVERITY_ERROR_STRING,
405				"Failed to reset bus",
406				" ");
407			ccb_h->status = CAM_REQ_CMP_ERR;
408		}
409		else
410			ccb_h->status = CAM_REQ_CMP;
411
412		mtx_lock(sc->sim_lock);
413		xpt_done(ccb);
414		break;
415
416	case XPT_SET_TRAN_SETTINGS:
417		tw_osli_dbg_dprintf(3, sc, "XPT_SET_TRAN_SETTINGS");
418
419		/*
420		 * This command is not supported, since it's very specific
421		 * to SCSI, and we are doing ATA.
422		 */
423  		ccb_h->status = CAM_FUNC_NOTAVAIL;
424  		xpt_done(ccb);
425  		break;
426
427	case XPT_GET_TRAN_SETTINGS:
428	{
429		struct ccb_trans_settings	*cts = &ccb->cts;
430		struct ccb_trans_settings_scsi *scsi =
431		    &cts->proto_specific.scsi;
432		struct ccb_trans_settings_spi *spi =
433		    &cts->xport_specific.spi;
434
435		cts->protocol = PROTO_SCSI;
436		cts->protocol_version = SCSI_REV_2;
437		cts->transport = XPORT_SPI;
438		cts->transport_version = 2;
439
440		spi->valid = CTS_SPI_VALID_DISC;
441		spi->flags = CTS_SPI_FLAGS_DISC_ENB;
442		scsi->valid = CTS_SCSI_VALID_TQ;
443		scsi->flags = CTS_SCSI_FLAGS_TAG_ENB;
444		tw_osli_dbg_dprintf(3, sc, "XPT_GET_TRAN_SETTINGS");
445		ccb_h->status = CAM_REQ_CMP;
446		xpt_done(ccb);
447		break;
448	}
449
450	case XPT_CALC_GEOMETRY:
451		tw_osli_dbg_dprintf(3, sc, "XPT_CALC_GEOMETRY");
452		cam_calc_geometry(&ccb->ccg, 1/* extended */);
453		xpt_done(ccb);
454		break;
455
456	case XPT_PATH_INQ:    /* Path inquiry -- get twa properties */
457	{
458		struct ccb_pathinq	*path_inq = &ccb->cpi;
459
460		tw_osli_dbg_dprintf(3, sc, "XPT_PATH_INQ request");
461
462		path_inq->version_num = 1;
463		path_inq->hba_inquiry = 0;
464		path_inq->target_sprt = 0;
465		path_inq->hba_misc = 0;
466		path_inq->hba_eng_cnt = 0;
467		path_inq->max_target = TW_CL_MAX_NUM_UNITS;
468		path_inq->max_lun = TW_CL_MAX_NUM_LUNS - 1;
469		path_inq->unit_number = cam_sim_unit(sim);
470		path_inq->bus_id = cam_sim_bus(sim);
471		path_inq->initiator_id = TW_CL_MAX_NUM_UNITS;
472		path_inq->base_transfer_speed = 100000;
473		strncpy(path_inq->sim_vid, "FreeBSD", SIM_IDLEN);
474		strncpy(path_inq->hba_vid, "3ware", HBA_IDLEN);
475		strncpy(path_inq->dev_name, cam_sim_name(sim), DEV_IDLEN);
476                path_inq->transport = XPORT_SPI;
477                path_inq->transport_version = 2;
478                path_inq->protocol = PROTO_SCSI;
479                path_inq->protocol_version = SCSI_REV_2;
480		ccb_h->status = CAM_REQ_CMP;
481		xpt_done(ccb);
482		break;
483	}
484
485	default:
486		tw_osli_dbg_dprintf(3, sc, "func_code = %x", ccb_h->func_code);
487		ccb_h->status = CAM_REQ_INVALID;
488		xpt_done(ccb);
489		break;
490	}
491}
492
493
494
495/*
496 * Function name:	twa_poll
497 * Description:		Driver entry point called when interrupts are not
498 *			available.
499 *
500 * Input:		sim	-- sim corresponding to the controller
501 * Output:		None
502 * Return value:	None
503 */
504TW_VOID
505twa_poll(struct cam_sim *sim)
506{
507	struct twa_softc *sc = (struct twa_softc *)(cam_sim_softc(sim));
508
509	tw_osli_dbg_dprintf(3, sc, "entering; sc = %p", sc);
510	/*
511	 * It's been observed that twa_poll can get called (from
512	 * dashutdown --> xpt_polled_action) even when interrupts are
513	 * active, in which case, the ISR might clear the interrupt,
514	 * leaving the call to tw_cl_interrupt below, no way of determining
515	 * that the response from firmware is ready, resulting in
516	 * tw_cl_deferred_interrupt never getting called.  To cover this case,
517	 * we will make the call to tw_cl_deferred_interrupt not dependent
518	 * on the return value from tw_cl_interrupt.
519	 */
520	tw_cl_interrupt(&(sc->ctlr_handle));
521	tw_cl_deferred_interrupt(&(sc->ctlr_handle));
522	tw_osli_dbg_dprintf(3, sc, "exiting; sc = %p", sc);
523}
524
525
526
527/*
528 * Function name:	twa_timeout
529 * Description:		Driver entry point for being alerted on a request
530 *			timing out.
531 *
532 * Input:		arg	-- ptr to timed out request
533 * Output:		None
534 * Return value:	None
535 */
536static TW_VOID
537twa_timeout(TW_VOID *arg)
538{
539	struct tw_osli_req_context	*req =
540		(struct tw_osli_req_context *)arg;
541
542	tw_cl_create_event(&(req->ctlr->ctlr_handle), TW_CL_TRUE,
543		TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
544		0x210B, 0x1, TW_CL_SEVERITY_ERROR_STRING,
545		"Request timed out!",
546		"request = %p", req);
547	tw_cl_reset_ctlr(&(req->ctlr->ctlr_handle));
548}
549
550
551
552/*
553 * Function name:	tw_osli_request_bus_scan
554 * Description:		Requests CAM for a scan of the bus.
555 *
556 * Input:		sc	-- ptr to per ctlr structure
557 * Output:		None
558 * Return value:	0	-- success
559 *			non-zero-- failure
560 */
561TW_INT32
562tw_osli_request_bus_scan(struct twa_softc *sc)
563{
564	struct cam_path	*path;
565	union ccb	*ccb;
566
567	tw_osli_dbg_dprintf(3, sc, "entering");
568
569	/* If we get here before sc->sim is initialized, return an error. */
570	if (!(sc->sim))
571		return(ENXIO);
572	if ((ccb = malloc(sizeof(union ccb), M_TEMP, M_WAITOK)) == NULL)
573		return(ENOMEM);
574	bzero(ccb, sizeof(union ccb));
575	mtx_lock(sc->sim_lock);
576	if (xpt_create_path(&path, xpt_periph, cam_sim_path(sc->sim),
577			    CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
578		free(ccb, M_TEMP);
579		mtx_unlock(sc->sim_lock);
580		return(EIO);
581	}
582
583	/* Release simq at the end of a reset */
584	if (sc->state & TW_OSLI_CTLR_STATE_SIMQ_FROZEN) {
585		xpt_release_simq(sc->sim, 1);
586		sc->state &= ~TW_OSLI_CTLR_STATE_SIMQ_FROZEN;
587	}
588
589	xpt_setup_ccb(&ccb->ccb_h, path, 5);
590	ccb->ccb_h.func_code = XPT_SCAN_BUS;
591	ccb->ccb_h.cbfcnp = twa_bus_scan_cb;
592	ccb->crcn.flags = CAM_FLAG_NONE;
593	xpt_action(ccb);
594	mtx_unlock(sc->sim_lock);
595	return(0);
596}
597
598
599
600/*
601 * Function name:	twa_bus_scan_cb
602 * Description:		Callback from CAM on a bus scan request.
603 *
604 * Input:		periph	-- we don't use this
605 *			ccb	-- bus scan request ccb that we sent to CAM
606 * Output:		None
607 * Return value:	None
608 */
609static TW_VOID
610twa_bus_scan_cb(struct cam_periph *periph, union ccb *ccb)
611{
612	tw_osli_dbg_printf(3, "entering");
613
614	if (ccb->ccb_h.status != CAM_REQ_CMP)
615		printf("cam_scan_callback: failure status = %x\n",
616			ccb->ccb_h.status);
617	else
618		tw_osli_dbg_printf(3, "success");
619
620	xpt_free_path(ccb->ccb_h.path);
621	free(ccb, M_TEMP);
622}
623
624
625
626/*
627 * Function name:	tw_osli_allow_new_requests
628 * Description:		Sets the appropriate status bits in a ccb such that,
629 *			when the ccb is completed by a call to xpt_done,
630 *			CAM knows that it's ok to unfreeze the flow of new
631 *			requests to this controller, if the flow is frozen.
632 *
633 * Input:		sc	-- ptr to OSL internal ctlr context
634 *			ccb	-- ptr to CAM request
635 * Output:		None
636 * Return value:	None
637 */
638TW_VOID
639tw_osli_allow_new_requests(struct twa_softc *sc, TW_VOID *ccb)
640{
641	((union ccb *)(ccb))->ccb_h.status |= CAM_RELEASE_SIMQ;
642	sc->state &= ~TW_OSLI_CTLR_STATE_SIMQ_FROZEN;
643}
644
645
646
647/*
648 * Function name:	tw_osli_disallow_new_requests
649 * Description:		Calls the appropriate CAM function, so as to freeze
650 *			the flow of new requests from CAM to this controller.
651 *
652 * Input:		sc	-- ptr to OSL internal ctlr context
653 * Output:		None
654 * Return value:	None
655 */
656TW_VOID
657tw_osli_disallow_new_requests(struct twa_softc *sc)
658{
659	/* Don't double freeze if already frozen */
660	if ((sc->state & TW_OSLI_CTLR_STATE_SIMQ_FROZEN) == 0) {
661		mtx_lock(sc->sim_lock);
662		xpt_freeze_simq(sc->sim, 1);
663		mtx_unlock(sc->sim_lock);
664		sc->state |= TW_OSLI_CTLR_STATE_SIMQ_FROZEN;
665	}
666}
667
668
669
670/*
671 * Function name:	tw_osl_ctlr_busy
672 * Description:		CL calls this function on cmd queue full or otherwise,
673 *			when it is too busy to accept new requests.
674 *
675 * Input:		ctlr_handle	-- ptr to controller handle
676 *			req_handle	-- ptr to request handle sent by OSL.
677 * Output:		None
678 * Return value:	None
679 */
680TW_VOID
681tw_osl_ctlr_busy(struct tw_cl_ctlr_handle *ctlr_handle,
682	struct tw_cl_req_handle *req_handle)
683{
684	tw_osli_disallow_new_requests(ctlr_handle->osl_ctlr_ctxt);
685}
686
687
688
689/*
690 * Function name:	tw_osl_scan_bus
691 * Description:		CL calls this function to request for a bus scan.
692 *
693 * Input:		ctlr_handle	-- ptr to controller handle
694 * Output:		None
695 * Return value:	None
696 */
697TW_VOID
698tw_osl_scan_bus(struct tw_cl_ctlr_handle *ctlr_handle)
699{
700	struct twa_softc	*sc = ctlr_handle->osl_ctlr_ctxt;
701	TW_INT32		error;
702
703	if ((error = tw_osli_request_bus_scan(sc)))
704		tw_osli_printf(sc, "error = %d",
705			TW_CL_SEVERITY_ERROR_STRING,
706			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
707			0x2109,
708			"Bus scan request to CAM failed",
709			error);
710}
711
712
713
714/*
715 * Function name:	tw_osl_complete_io
716 * Description:		Called to complete CAM scsi requests.
717 *
718 * Input:		req_handle	-- ptr to request handle
719 * Output:		None
720 * Return value:	None
721 */
722TW_VOID
723tw_osl_complete_io(struct tw_cl_req_handle *req_handle)
724{
725	struct tw_osli_req_context	*req = req_handle->osl_req_ctxt;
726	struct tw_cl_req_packet		*req_pkt =
727		(struct tw_cl_req_packet *)(&req->req_pkt);
728	struct tw_cl_scsi_req_packet	*scsi_req;
729	struct twa_softc		*sc = req->ctlr;
730	union ccb			*ccb = (union ccb *)(req->orig_req);
731
732	tw_osli_dbg_dprintf(10, sc, "entering");
733
734	if (req->state != TW_OSLI_REQ_STATE_BUSY)
735		tw_osli_printf(sc, "request = %p, status = %d",
736			TW_CL_SEVERITY_ERROR_STRING,
737			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
738			0x210A,
739			"Unposted command completed!!",
740			req, req->state);
741
742	/*
743	 * Remove request from the busy queue.  Just mark it complete.
744	 * There's no need to move it into the complete queue as we are
745	 * going to be done with it right now.
746	 */
747	req->state = TW_OSLI_REQ_STATE_COMPLETE;
748	tw_osli_req_q_remove_item(req, TW_OSLI_BUSY_Q);
749
750	tw_osli_unmap_request(req);
751
752	untimeout(twa_timeout, req, ccb->ccb_h.timeout_ch);
753	if (req->error_code) {
754		/* This request never got submitted to the firmware. */
755		if (req->error_code == EBUSY) {
756			/*
757			 * Cmd queue is full, or the Common Layer is out of
758			 * resources.  The simq will already have been frozen
759			 * by CL's call to tw_osl_ctlr_busy, and this will
760			 * maintain ccb ordering.  The next ccb that gets
761			 * completed will unfreeze the simq.
762			 */
763			ccb->ccb_h.status |= CAM_REQUEUE_REQ;
764		}
765		else if (req->error_code == EFBIG)
766			ccb->ccb_h.status = CAM_REQ_TOO_BIG;
767		else
768			ccb->ccb_h.status = CAM_REQ_CMP_ERR;
769	} else {
770		scsi_req = &(req_pkt->gen_req_pkt.scsi_req);
771		if (req_pkt->status == TW_CL_ERR_REQ_SUCCESS)
772			ccb->ccb_h.status = CAM_REQ_CMP;
773		else {
774			if (req_pkt->status & TW_CL_ERR_REQ_INVALID_TARGET)
775				ccb->ccb_h.status |= CAM_TID_INVALID;
776			else if (req_pkt->status & TW_CL_ERR_REQ_INVALID_LUN)
777				ccb->ccb_h.status |= CAM_LUN_INVALID;
778			else if (req_pkt->status & TW_CL_ERR_REQ_SCSI_ERROR)
779				ccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
780			else if (req_pkt->status & TW_CL_ERR_REQ_BUS_RESET)
781				ccb->ccb_h.status |= CAM_SCSI_BUS_RESET;
782			/*
783			 * If none of the above errors occurred, simply
784			 * mark completion error.
785			 */
786			if (ccb->ccb_h.status == 0)
787				ccb->ccb_h.status = CAM_REQ_CMP_ERR;
788
789			if (req_pkt->status & TW_CL_ERR_REQ_AUTO_SENSE_VALID) {
790				ccb->csio.sense_len = scsi_req->sense_len;
791				ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
792			}
793		}
794
795		ccb->csio.scsi_status = scsi_req->scsi_status;
796		/* If simq is frozen, unfreeze it. */
797		if (sc->state & TW_OSLI_CTLR_STATE_SIMQ_FROZEN)
798			tw_osli_allow_new_requests(sc, (TW_VOID *)ccb);
799	}
800
801	ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
802	mtx_lock(sc->sim_lock);
803	xpt_done(ccb);
804	mtx_unlock(sc->sim_lock);
805	if (! req->error_code)
806		 /* twa_action will free the request otherwise */
807		tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q);
808}
809
810