Beispiel #1
0
static TW_VOID
twa_watchdog(TW_VOID *arg)
{
	struct tw_cl_ctlr_handle *ctlr_handle =
		(struct tw_cl_ctlr_handle *)arg;
	struct twa_softc		*sc = ctlr_handle->osl_ctlr_ctxt;
	int				i;
	int				i_need_a_reset = 0;
	int				driver_is_active = 0;
	TW_UINT64			current_time;
	struct tw_osli_req_context	*my_req;


//==============================================================================
	current_time = (TW_UINT64) (tw_osl_get_local_time());

	for (i = 0; i < TW_OSLI_MAX_NUM_REQUESTS; i++) {
		my_req = &(sc->req_ctx_buf[i]);

		if ((my_req->state == TW_OSLI_REQ_STATE_BUSY) &&
			(my_req->deadline) &&
			(my_req->deadline < current_time)) {
			tw_cl_set_reset_needed(ctlr_handle);
#ifdef    TW_OSL_DEBUG
			device_printf((sc)->bus_dev, "Request %d timed out! d = %llu, c = %llu\n", i, my_req->deadline, current_time);
#else  /* TW_OSL_DEBUG */
			device_printf((sc)->bus_dev, "Request %d timed out!\n", i);
#endif /* TW_OSL_DEBUG */
			break;
		}
	}
//==============================================================================

	i_need_a_reset = tw_cl_is_reset_needed(ctlr_handle);

	i = (int) ((sc->watchdog_index++) & 1);

	driver_is_active = tw_cl_is_active(ctlr_handle);

	if (i_need_a_reset) {
#ifdef    TW_OSL_DEBUG
		device_printf((sc)->bus_dev, "Watchdog rescheduled in 70 seconds\n");
#endif /* TW_OSL_DEBUG */
		callout_reset(&(sc->watchdog_callout[i]), 70*hz, twa_watchdog, &sc->ctlr_handle);
		tw_cl_reset_ctlr(ctlr_handle);
#ifdef    TW_OSL_DEBUG
		device_printf((sc)->bus_dev, "Watchdog reset completed!\n");
#endif /* TW_OSL_DEBUG */
	} else if (driver_is_active) {
		callout_reset(&(sc->watchdog_callout[i]),  5*hz, twa_watchdog, &sc->ctlr_handle);
	}
#ifdef    TW_OSL_DEBUG
	if (i_need_a_reset)
		device_printf((sc)->bus_dev, "i_need_a_reset = %d, "
		"driver_is_active = %d\n",
		i_need_a_reset, driver_is_active);
#endif /* TW_OSL_DEBUG */
}
Beispiel #2
0
/*
 * Function name:	twa_action
 * Description:		Driver entry point for CAM's use.
 *
 * Input:		sim	-- sim corresponding to the ctlr
 *			ccb	-- ptr to CAM request
 * Output:		None
 * Return value:	None
 */
TW_VOID
twa_action(struct cam_sim *sim, union ccb *ccb)
{
	struct twa_softc	*sc = (struct twa_softc *)cam_sim_softc(sim);
	struct ccb_hdr		*ccb_h = &(ccb->ccb_h);

	switch (ccb_h->func_code) {
	case XPT_SCSI_IO:	/* SCSI I/O */
	{
		struct tw_osli_req_context	*req;

		req = tw_osli_get_request(sc);
		if (req == NULL) {
			tw_osli_dbg_dprintf(2, sc, "Cannot get request pkt.");
			/*
			 * Freeze the simq to maintain ccb ordering.  The next
			 * ccb that gets completed will unfreeze the simq.
			 */
			ccb_h->status &= ~CAM_SIM_QUEUED;
			ccb_h->status |= CAM_REQUEUE_REQ;
			xpt_done(ccb);
			break;
		}

		if ((tw_cl_is_reset_needed(&(req->ctlr->ctlr_handle)))) {
			ccb_h->status &= ~CAM_SIM_QUEUED;
			ccb_h->status |= CAM_REQUEUE_REQ;
			xpt_done(ccb);
			tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q);
			break;
		}

		req->req_handle.osl_req_ctxt = req;
		req->req_handle.is_io = TW_CL_TRUE;
		req->orig_req = ccb;
		if (tw_osli_execute_scsi(req, ccb))
			tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q);
		break;
	}

	case XPT_ABORT:
		tw_osli_dbg_dprintf(2, sc, "Abort request.");
		ccb_h->status = CAM_UA_ABORT;
		xpt_done(ccb);
		break;

	case XPT_RESET_BUS:
		tw_cl_create_event(&(sc->ctlr_handle), TW_CL_FALSE,
			TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
			0x2108, 0x3, TW_CL_SEVERITY_INFO_STRING,
			"Received Reset Bus request from CAM",
			" ");

		tw_cl_set_reset_needed(&(sc->ctlr_handle));
		ccb_h->status = CAM_REQ_CMP;
		xpt_done(ccb);
		break;

	case XPT_SET_TRAN_SETTINGS:
		tw_osli_dbg_dprintf(3, sc, "XPT_SET_TRAN_SETTINGS");

		/*
		 * This command is not supported, since it's very specific
		 * to SCSI, and we are doing ATA.
		 */
  		ccb_h->status = CAM_FUNC_NOTAVAIL;
  		xpt_done(ccb);
  		break;

	case XPT_GET_TRAN_SETTINGS: 
	{
		struct ccb_trans_settings	*cts = &ccb->cts;
		struct ccb_trans_settings_scsi *scsi =
		    &cts->proto_specific.scsi;
		struct ccb_trans_settings_spi *spi =
		    &cts->xport_specific.spi;

		cts->protocol = PROTO_SCSI;
		cts->protocol_version = SCSI_REV_2;
		cts->transport = XPORT_SPI;
		cts->transport_version = 2;

		spi->valid = CTS_SPI_VALID_DISC;
		spi->flags = CTS_SPI_FLAGS_DISC_ENB;
		scsi->valid = CTS_SCSI_VALID_TQ;
		scsi->flags = CTS_SCSI_FLAGS_TAG_ENB;
		tw_osli_dbg_dprintf(3, sc, "XPT_GET_TRAN_SETTINGS");
		ccb_h->status = CAM_REQ_CMP;
		xpt_done(ccb);
		break;
	}

	case XPT_CALC_GEOMETRY:
		tw_osli_dbg_dprintf(3, sc, "XPT_CALC_GEOMETRY");
		cam_calc_geometry(&ccb->ccg, 1/* extended */);
		xpt_done(ccb);
		break;

	case XPT_PATH_INQ:    /* Path inquiry -- get twa properties */
	{
		struct ccb_pathinq	*path_inq = &ccb->cpi;

		tw_osli_dbg_dprintf(3, sc, "XPT_PATH_INQ request");

		path_inq->version_num = 1;
		path_inq->hba_inquiry = 0;
		path_inq->target_sprt = 0;
		path_inq->hba_misc = 0;
		path_inq->hba_eng_cnt = 0;
		path_inq->max_target = TW_CL_MAX_NUM_UNITS;
		path_inq->max_lun = TW_CL_MAX_NUM_LUNS - 1;
		path_inq->unit_number = cam_sim_unit(sim);
		path_inq->bus_id = cam_sim_bus(sim);
		path_inq->initiator_id = TW_CL_MAX_NUM_UNITS;
		path_inq->base_transfer_speed = 100000;
		strlcpy(path_inq->sim_vid, "FreeBSD", SIM_IDLEN);
		strlcpy(path_inq->hba_vid, "3ware", HBA_IDLEN);
		strlcpy(path_inq->dev_name, cam_sim_name(sim), DEV_IDLEN);
		path_inq->transport = XPORT_SPI;
		path_inq->transport_version = 2;
		path_inq->protocol = PROTO_SCSI;
		path_inq->protocol_version = SCSI_REV_2;
		path_inq->maxio = TW_CL_MAX_IO_SIZE;
		ccb_h->status = CAM_REQ_CMP;
		xpt_done(ccb);
		break;
	}

	default:
		tw_osli_dbg_dprintf(3, sc, "func_code = %x", ccb_h->func_code);
		ccb_h->status = CAM_REQ_INVALID;
		xpt_done(ccb);
		break;
	}
}