/**
 * mrsas_action:            SIM callback entry point   
 * input:                   pointer to SIM 
 *                          pointer to CAM Control Block
 *
 * This function processes CAM subsystem requests. The type of request is
 * stored in ccb->ccb_h.func_code.  The preprocessor #ifdef is necessary
 * because ccb->cpi.maxio is not supported for FreeBSD version 7.4 or 
 * earlier.   
 */
static void mrsas_action(struct cam_sim *sim, union ccb *ccb)
{
    struct mrsas_softc *sc = (struct mrsas_softc *)cam_sim_softc(sim);
    struct ccb_hdr *ccb_h = &(ccb->ccb_h);
    u_int32_t device_id;

    switch (ccb->ccb_h.func_code) {
        case XPT_SCSI_IO:
        {
            device_id = ccb_h->target_id;

            /* 
             * bus 0 is LD, bus 1 is for system-PD 
             */ 
            if (cam_sim_bus(sim) == 1 && 
                sc->pd_list[device_id].driveState != MR_PD_STATE_SYSTEM) {
                ccb->ccb_h.status |= CAM_DEV_NOT_THERE;
                xpt_done(ccb);
            }
            else {
                if (mrsas_startio(sc, sim, ccb)){
                    ccb->ccb_h.status |= CAM_REQ_INVALID;
                    xpt_done(ccb);
                }
            }
            break;
        }
        case XPT_ABORT:
        {
            ccb->ccb_h.status = CAM_UA_ABORT;
            xpt_done(ccb);
            break;
        }
        case XPT_RESET_BUS:
        {
            xpt_done(ccb);
            break;
        }
        case XPT_GET_TRAN_SETTINGS:
        {
            ccb->cts.protocol = PROTO_SCSI;
            ccb->cts.protocol_version = SCSI_REV_2;
            ccb->cts.transport = XPORT_SPI;
            ccb->cts.transport_version = 2;  
            ccb->cts.xport_specific.spi.valid = CTS_SPI_VALID_DISC;
            ccb->cts.xport_specific.spi.flags = CTS_SPI_FLAGS_DISC_ENB;
            ccb->cts.proto_specific.scsi.valid = CTS_SCSI_VALID_TQ;
            ccb->cts.proto_specific.scsi.flags = CTS_SCSI_FLAGS_TAG_ENB;
            ccb->ccb_h.status = CAM_REQ_CMP;
            xpt_done(ccb);
            break;
        }
        case XPT_SET_TRAN_SETTINGS:
        {
            ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; 
            xpt_done(ccb);
            break;
        }
        case XPT_CALC_GEOMETRY:
        {
            cam_calc_geometry(&ccb->ccg, 1);   
            xpt_done(ccb);
            break;
        }
        case XPT_PATH_INQ:
        {
            ccb->cpi.version_num = 1;
            ccb->cpi.hba_inquiry = 0;
            ccb->cpi.target_sprt = 0;
            ccb->cpi.hba_misc = 0;
            ccb->cpi.hba_eng_cnt = 0;
            ccb->cpi.max_lun = MRSAS_SCSI_MAX_LUNS;
            ccb->cpi.unit_number = cam_sim_unit(sim);
            ccb->cpi.bus_id = cam_sim_bus(sim);
            ccb->cpi.initiator_id = MRSAS_SCSI_INITIATOR_ID; 
            ccb->cpi.base_transfer_speed = 150000; 
            strncpy(ccb->cpi.sim_vid, "FreeBSD", SIM_IDLEN);
            strncpy(ccb->cpi.hba_vid, "LSI", HBA_IDLEN);
            strncpy(ccb->cpi.dev_name, cam_sim_name(sim), DEV_IDLEN);
            ccb->cpi.transport = XPORT_SPI;
            ccb->cpi.transport_version = 2;
            ccb->cpi.protocol = PROTO_SCSI;
            ccb->cpi.protocol_version = SCSI_REV_2;
            if (ccb->cpi.bus_id == 0)
                ccb->cpi.max_target = MRSAS_MAX_LD-1;
            else
                ccb->cpi.max_target = MRSAS_MAX_PD-1;
            ccb->cpi.maxio = MRSAS_MAX_IO_SIZE;
            ccb->ccb_h.status = CAM_REQ_CMP;
            xpt_done(ccb);
            break;
        }
        default:
        {
            ccb->ccb_h.status = CAM_REQ_INVALID;
            xpt_done(ccb);
            break;
        }
    }
}
Esempio n. 2
0
static void
ahbpoll(struct cam_sim *sim)
{
	ahbintr(cam_sim_softc(sim));
}
Esempio n. 3
0
static void
ahaaction(struct cam_sim *sim, union ccb *ccb)
{
	struct	aha_softc *aha;

	CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("ahaaction\n"));

	aha = (struct aha_softc *)cam_sim_softc(sim);
	mtx_assert(&aha->lock, MA_OWNED);

	switch (ccb->ccb_h.func_code) {
	/* Common cases first */
	case XPT_SCSI_IO:	/* Execute the requested I/O operation */
	case XPT_RESET_DEV:	/* Bus Device Reset the specified SCSI device */	{
		struct	aha_ccb	*accb;
		struct	aha_hccb *hccb;

		/*
		 * Get an accb to use.
		 */
		if ((accb = ahagetccb(aha)) == NULL) {
			aha->resource_shortage = TRUE;
			xpt_freeze_simq(aha->sim, /*count*/1);
			ccb->ccb_h.status = CAM_REQUEUE_REQ;
			xpt_done(ccb);
			return;
		}
		hccb = &accb->hccb;

		/*
		 * So we can find the ACCB when an abort is requested
		 */
		accb->ccb = ccb;
		ccb->ccb_h.ccb_accb_ptr = accb;
		ccb->ccb_h.ccb_aha_ptr = aha;

		/*
		 * Put all the arguments for the xfer in the accb
		 */
		hccb->target = ccb->ccb_h.target_id;
		hccb->lun = ccb->ccb_h.target_lun;
		hccb->ahastat = 0;
		hccb->sdstat = 0;

		if (ccb->ccb_h.func_code == XPT_SCSI_IO) {
			struct ccb_scsiio *csio;
			struct ccb_hdr *ccbh;
			int error;

			csio = &ccb->csio;
			ccbh = &csio->ccb_h;
			hccb->opcode = aha->ccb_ccb_opcode;
			hccb->datain = (ccb->ccb_h.flags & CAM_DIR_IN) != 0;
			hccb->dataout = (ccb->ccb_h.flags & CAM_DIR_OUT) != 0;
			hccb->cmd_len = csio->cdb_len;
			if (hccb->cmd_len > sizeof(hccb->scsi_cdb)) {
				ccb->ccb_h.status = CAM_REQ_INVALID;
				ahafreeccb(aha, accb);
				xpt_done(ccb);
				return;
			}
			hccb->sense_len = csio->sense_len;
			if ((ccbh->flags & CAM_CDB_POINTER) != 0) {
				if ((ccbh->flags & CAM_CDB_PHYS) == 0) {
					bcopy(csio->cdb_io.cdb_ptr,
					      hccb->scsi_cdb, hccb->cmd_len);
				} else {
					/* I guess I could map it in... */
					ccbh->status = CAM_REQ_INVALID;
					ahafreeccb(aha, accb);
					xpt_done(ccb);
					return;
				}
			} else {
				bcopy(csio->cdb_io.cdb_bytes,
				      hccb->scsi_cdb, hccb->cmd_len);
			}
			/*
			 * If we have any data to send with this command,
			 * map it into bus space.
			 */

			error = bus_dmamap_load_ccb(
			    aha->buffer_dmat,
			    accb->dmamap,
			    ccb,
			    ahaexecuteccb,
			    accb,
			    /*flags*/0);
			if (error == EINPROGRESS) {
				/*
				 * So as to maintain ordering, freeze the
				 * controller queue until our mapping is
				 * returned.
				 */
				xpt_freeze_simq(aha->sim, 1);
				csio->ccb_h.status |= CAM_RELEASE_SIMQ;
			}
		} else {
			hccb->opcode = INITIATOR_BUS_DEV_RESET;
			/* No data transfer */
			hccb->datain = TRUE;
			hccb->dataout = TRUE;
			hccb->cmd_len = 0;
			hccb->sense_len = 0;
			ahaexecuteccb(accb, NULL, 0, 0);
		}
		break;
	}
	case XPT_ABORT:			/* Abort the specified CCB */
		/* XXX Implement */
		ccb->ccb_h.status = CAM_REQ_INVALID;
		xpt_done(ccb);
		break;
	case XPT_SET_TRAN_SETTINGS:
		/* XXX Implement */
		ccb->ccb_h.status = CAM_PROVIDE_FAIL;
		xpt_done(ccb);
		break;
	case XPT_GET_TRAN_SETTINGS:
	/* Get default/user set transfer settings for the target */
	{
		struct	ccb_trans_settings *cts = &ccb->cts;
		u_int	target_mask = 0x01 << ccb->ccb_h.target_id;
		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;
		if (cts->type == CTS_TYPE_USER_SETTINGS) {
			spi->flags = 0;
			if ((aha->disc_permitted & target_mask) != 0)
				spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
			spi->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
			if ((aha->sync_permitted & target_mask) != 0) {
				if (aha->boardid >= BOARD_1542CF)
					spi->sync_period = 25;
				else
					spi->sync_period = 50;
			} else {
				spi->sync_period = 0;
			}

			if (spi->sync_period != 0)
				spi->sync_offset = 15;

			spi->valid = CTS_SPI_VALID_SYNC_RATE
				   | CTS_SPI_VALID_SYNC_OFFSET
				   | CTS_SPI_VALID_BUS_WIDTH
				   | CTS_SPI_VALID_DISC;
			scsi->valid = CTS_SCSI_VALID_TQ;
		} else {
			ahafetchtransinfo(aha, cts);
		}

		ccb->ccb_h.status = CAM_REQ_CMP;
		xpt_done(ccb);
		break;
	}
	case XPT_CALC_GEOMETRY:
	{
		struct	  ccb_calc_geometry *ccg;
		uint32_t size_mb;
		uint32_t secs_per_cylinder;

		ccg = &ccb->ccg;
		size_mb = ccg->volume_size
			/ ((1024L * 1024L) / ccg->block_size);
		if (size_mb >= 1024 && (aha->extended_trans != 0)) {
			if (size_mb >= 2048) {
				ccg->heads = 255;
				ccg->secs_per_track = 63;
			} else {
				ccg->heads = 128;
				ccg->secs_per_track = 32;
			}
		} else {
			ccg->heads = 64;
			ccg->secs_per_track = 32;
		}
		secs_per_cylinder = ccg->heads * ccg->secs_per_track;
		ccg->cylinders = ccg->volume_size / secs_per_cylinder;
		ccb->ccb_h.status = CAM_REQ_CMP;
		xpt_done(ccb);
		break;
	}
	case XPT_RESET_BUS:		/* Reset the specified SCSI bus */
		ahareset(aha, /*hardreset*/TRUE);
		ccb->ccb_h.status = CAM_REQ_CMP;
		xpt_done(ccb);
		break;
	case XPT_TERM_IO:		/* Terminate the I/O process */
		/* XXX Implement */
		ccb->ccb_h.status = CAM_REQ_INVALID;
		xpt_done(ccb);
		break;
	case XPT_PATH_INQ:		/* Path routing inquiry */
	{
		struct ccb_pathinq *cpi = &ccb->cpi;

		cpi->version_num = 1; /* XXX??? */
		cpi->hba_inquiry = PI_SDTR_ABLE;
		cpi->target_sprt = 0;
		cpi->hba_misc = 0;
		cpi->hba_eng_cnt = 0;
		cpi->max_target = 7;
		cpi->max_lun = 7;
		cpi->initiator_id = aha->scsi_id;
		cpi->bus_id = cam_sim_bus(sim);
		cpi->base_transfer_speed = 3300;
		strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
		strlcpy(cpi->hba_vid, "Adaptec", HBA_IDLEN);
		strlcpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
		cpi->unit_number = cam_sim_unit(sim);
		cpi->transport = XPORT_SPI;
		cpi->transport_version = 2;
		cpi->protocol = PROTO_SCSI;
		cpi->protocol_version = SCSI_REV_2;
		cpi->ccb_h.status = CAM_REQ_CMP;
		xpt_done(ccb);
		break;
	}
	default:
		ccb->ccb_h.status = CAM_REQ_INVALID;
		xpt_done(ccb);
		break;
	}
}
Esempio n. 4
0
/*
 * Action function - dispatch command
 */
static
void
ahci_xpt_action(struct cam_sim *sim, union ccb *ccb)
{
	struct ahci_port *ap;
	struct ata_port	 *at, *atx;
	struct ccb_hdr *ccbh;
	int unit;

	/* XXX lock */
	ap = cam_sim_softc(sim);
	atx = NULL;
	KKASSERT(ap != NULL);
	ccbh = &ccb->ccb_h;
	unit = cam_sim_unit(sim);

	/*
	 * Early failure checks.  These checks do not apply to XPT_PATH_INQ,
	 * otherwise the bus rescan will not remove the dead devices when
	 * unplugging a PM.
	 *
	 * For non-wildcards we have one target (0) and one lun (0),
	 * unless we have a port multiplier.
	 *
	 * A wildcard target indicates only the general bus is being
	 * probed.
	 *
	 * Calculate at and atx.  at is always non-NULL.  atx is only
	 * NULL for direct-attached devices.  It will be non-NULL for
	 * devices behind a port multiplier.
	 *
	 * XXX What do we do with a LUN wildcard?
	 */
	if (ccbh->target_id != CAM_TARGET_WILDCARD &&
	    ccbh->func_code != XPT_PATH_INQ) {
		if (ap->ap_type == ATA_PORT_T_NONE) {
			ccbh->status = CAM_DEV_NOT_THERE;
			xpt_done(ccb);
			return;
		}
		if (ccbh->target_id < 0 || ccbh->target_id >= ap->ap_pmcount) {
			ccbh->status = CAM_DEV_NOT_THERE;
			xpt_done(ccb);
			return;
		}
		at = ap->ap_ata[ccbh->target_id];
		if (ap->ap_type == ATA_PORT_T_PM)
			atx = at;

		if (ccbh->target_lun != CAM_LUN_WILDCARD && ccbh->target_lun) {
			ccbh->status = CAM_DEV_NOT_THERE;
			xpt_done(ccb);
			return;
		}
	} else {
		at = ap->ap_ata[0];
	}

	/*
	 * Switch on the meta XPT command
	 */
	switch(ccbh->func_code) {
	case XPT_ENG_EXEC:
		/*
		 * This routine is called after a port multiplier has been
		 * probed.
		 */
		ccbh->status = CAM_REQ_CMP;
		ahci_os_lock_port(ap);
		ahci_port_state_machine(ap, 0);
		ahci_os_unlock_port(ap);
		xpt_done(ccb);
		ahci_xpt_rescan(ap);
		break;
	case XPT_PATH_INQ:
		/*
		 * This command always succeeds, otherwise the bus scan
		 * will not detach dead devices.
		 */
		ccb->cpi.version_num = 1;
		ccb->cpi.hba_inquiry = 0;
		ccb->cpi.target_sprt = 0;
		ccb->cpi.hba_misc = PIM_SEQSCAN;
		ccb->cpi.hba_eng_cnt = 0;
		bzero(ccb->cpi.vuhba_flags, sizeof(ccb->cpi.vuhba_flags));
		ccb->cpi.max_target = AHCI_MAX_PMPORTS - 1;
		ccb->cpi.max_lun = 0;
		ccb->cpi.async_flags = 0;
		ccb->cpi.hpath_id = 0;
		ccb->cpi.initiator_id = AHCI_MAX_PMPORTS - 1;
		ccb->cpi.unit_number = cam_sim_unit(sim);
		ccb->cpi.bus_id = cam_sim_bus(sim);
		ccb->cpi.base_transfer_speed = 150000;
		ccb->cpi.transport = XPORT_SATA;
		ccb->cpi.transport_version = 1;
		ccb->cpi.protocol = PROTO_SCSI;
		ccb->cpi.protocol_version = SCSI_REV_2;

		ccbh->status = CAM_REQ_CMP;
		if (ccbh->target_id == CAM_TARGET_WILDCARD) {
			ahci_os_lock_port(ap);
			ahci_port_state_machine(ap, 0);
			ahci_os_unlock_port(ap);
		} else {
			switch(ahci_pread(ap, AHCI_PREG_SSTS) &
			       AHCI_PREG_SSTS_SPD) {
			case AHCI_PREG_SSTS_SPD_GEN1:
				ccb->cpi.base_transfer_speed = 150000;
				break;
			case AHCI_PREG_SSTS_SPD_GEN2:
				ccb->cpi.base_transfer_speed = 300000;
				break;
			case AHCI_PREG_SSTS_SPD_GEN3:
				ccb->cpi.base_transfer_speed = 600000;
				break;
			default:
				/* unknown */
				ccb->cpi.base_transfer_speed = 1000;
				break;
			}
#if 0
			if (ap->ap_type == ATA_PORT_T_NONE)
				ccbh->status = CAM_DEV_NOT_THERE;
#endif
		}
		xpt_done(ccb);
		break;
	case XPT_RESET_DEV:
		ahci_os_lock_port(ap);
		if (ap->ap_type == ATA_PORT_T_NONE) {
			ccbh->status = CAM_DEV_NOT_THERE;
		} else {
			ahci_port_reset(ap, atx, 0);
			ccbh->status = CAM_REQ_CMP;
		}
		ahci_os_unlock_port(ap);
		xpt_done(ccb);
		break;
	case XPT_RESET_BUS:
		ahci_os_lock_port(ap);
		ahci_port_reset(ap, NULL, 1);
		ahci_os_unlock_port(ap);
		ccbh->status = CAM_REQ_CMP;
		xpt_done(ccb);
		break;
	case XPT_SET_TRAN_SETTINGS:
		ccbh->status = CAM_FUNC_NOTAVAIL;
		xpt_done(ccb);
		break;
	case XPT_GET_TRAN_SETTINGS:
		ccb->cts.protocol = PROTO_SCSI;
		ccb->cts.protocol_version = SCSI_REV_2;
		ccb->cts.transport = XPORT_SATA;
		ccb->cts.transport_version = XPORT_VERSION_UNSPECIFIED;
		ccb->cts.proto_specific.valid = 0;
		ccb->cts.xport_specific.valid = 0;
		ccbh->status = CAM_REQ_CMP;
		xpt_done(ccb);
		break;
	case XPT_CALC_GEOMETRY:
		cam_calc_geometry(&ccb->ccg, 1);
		xpt_done(ccb);
		break;
	case XPT_SCSI_IO:
		/*
		 * Our parallel startup code might have only probed through
		 * to the IDENT, so do the last step if necessary.
		 */
		if (at->at_probe == ATA_PROBE_NEED_IDENT)
			ahci_cam_probe(ap, atx);
		if (at->at_probe != ATA_PROBE_GOOD) {
			ccbh->status = CAM_DEV_NOT_THERE;
			xpt_done(ccb);
			break;
		}
		switch(at->at_type) {
		case ATA_PORT_T_DISK:
			ahci_xpt_scsi_disk_io(ap, atx, ccb);
			break;
		case ATA_PORT_T_ATAPI:
			ahci_xpt_scsi_atapi_io(ap, atx, ccb);
			break;
		default:
			ccbh->status = CAM_REQ_INVALID;
			xpt_done(ccb);
			break;
		}
		break;
	case XPT_TRIM:
	{
		scsi_cdb_t cdb;
		struct ccb_scsiio *csio;
		csio = &ccb->csio;
		cdb = (void *)((ccbh->flags & CAM_CDB_POINTER) ?
		    csio->cdb_io.cdb_ptr : csio->cdb_io.cdb_bytes);
		cdb->generic.opcode = TRIM;
		ahci_xpt_scsi_disk_io(ap, atx, ccb);
		break;
	}
	default:
		ccbh->status = CAM_REQ_INVALID;
		xpt_done(ccb);
		break;
	}
}
void isci_action(struct cam_sim *sim, union ccb *ccb)
{
	struct ISCI_CONTROLLER *controller =
	    (struct ISCI_CONTROLLER *)cam_sim_softc(sim);

	switch ( ccb->ccb_h.func_code ) {
	case XPT_PATH_INQ:
		{
			struct ccb_pathinq *cpi = &ccb->cpi;
			int bus = cam_sim_bus(sim);
			ccb->ccb_h.ccb_sim_ptr = sim;
			cpi->version_num = 1;
			cpi->hba_inquiry = PI_TAG_ABLE;
			cpi->target_sprt = 0;
			cpi->hba_misc = PIM_NOBUSRESET | PIM_SEQSCAN;
			cpi->hba_eng_cnt = 0;
			cpi->max_target = SCI_MAX_REMOTE_DEVICES - 1;
			cpi->max_lun = ISCI_MAX_LUN;
#if __FreeBSD_version >= 800102
			cpi->maxio = isci_io_request_get_max_io_size();
#endif
			cpi->unit_number = cam_sim_unit(sim);
			cpi->bus_id = bus;
			cpi->initiator_id = SCI_MAX_REMOTE_DEVICES;
			cpi->base_transfer_speed = 300000;
			strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
			strncpy(cpi->hba_vid, "Intel Corp.", HBA_IDLEN);
			strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
			cpi->transport = XPORT_SAS;
			cpi->transport_version = 0;
			cpi->protocol = PROTO_SCSI;
			cpi->protocol_version = SCSI_REV_SPC2;
			cpi->ccb_h.status = CAM_REQ_CMP;
			xpt_done(ccb);
		}
		break;
	case XPT_GET_TRAN_SETTINGS:
		{
			struct ccb_trans_settings *general_settings = &ccb->cts;
			struct ccb_trans_settings_sas *sas_settings =
			    &general_settings->xport_specific.sas;
			struct ccb_trans_settings_scsi *scsi_settings =
			    &general_settings->proto_specific.scsi;
			struct ISCI_REMOTE_DEVICE *remote_device;

			remote_device = controller->remote_device[ccb->ccb_h.target_id];

			if (remote_device == NULL) {
				ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
				ccb->ccb_h.status &= ~CAM_STATUS_MASK;
				ccb->ccb_h.status |= CAM_DEV_NOT_THERE;
				xpt_done(ccb);
				break;
			}

			general_settings->protocol = PROTO_SCSI;
			general_settings->transport = XPORT_SAS;
			general_settings->protocol_version = SCSI_REV_SPC2;
			general_settings->transport_version = 0;
			scsi_settings->valid = CTS_SCSI_VALID_TQ;
			scsi_settings->flags = CTS_SCSI_FLAGS_TAG_ENB;
			ccb->ccb_h.status &= ~CAM_STATUS_MASK;
			ccb->ccb_h.status |= CAM_REQ_CMP;

			sas_settings->bitrate =
			    isci_remote_device_get_bitrate(remote_device);

			if (sas_settings->bitrate != 0)
				sas_settings->valid = CTS_SAS_VALID_SPEED;

			xpt_done(ccb);
		}
		break;
	case XPT_SCSI_IO:
		isci_io_request_execute_scsi_io(ccb, controller);
		break;
#if __FreeBSD_version >= 900026
	case XPT_SMP_IO:
		isci_io_request_execute_smp_io(ccb, controller);
		break;
#endif
	case XPT_SET_TRAN_SETTINGS:
		ccb->ccb_h.status &= ~CAM_STATUS_MASK;
		ccb->ccb_h.status |= CAM_REQ_CMP;
		xpt_done(ccb);
		break;
	case XPT_CALC_GEOMETRY:
		cam_calc_geometry(&ccb->ccg, /*extended*/1);
		xpt_done(ccb);
		break;
	case XPT_RESET_DEV:
		{
			struct ISCI_REMOTE_DEVICE *remote_device =
			    controller->remote_device[ccb->ccb_h.target_id];

			if (remote_device != NULL)
				isci_remote_device_reset(remote_device, ccb);
			else {
				ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
				ccb->ccb_h.status &= ~CAM_STATUS_MASK;
				ccb->ccb_h.status |= CAM_DEV_NOT_THERE;
				xpt_done(ccb);
			}
		}
		break;
	case XPT_RESET_BUS:
		ccb->ccb_h.status = CAM_REQ_CMP;
		xpt_done(ccb);
		break;
	default:
		isci_log_message(0, "ISCI", "Unhandled func_code 0x%x\n",
		    ccb->ccb_h.func_code);
		ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
		ccb->ccb_h.status &= ~CAM_STATUS_MASK;
		ccb->ccb_h.status |= CAM_REQ_INVALID;
		xpt_done(ccb);
		break;
	}
}
Esempio n. 6
0
static void hpt_poll(struct cam_sim *sim)
{
	PVBUS_EXT vbus_ext = cam_sim_softc(sim);
	hpt_assert_vbus_locked(vbus_ext);
	ldm_intr((PVBUS)vbus_ext->vbus);
}
Esempio n. 7
0
static void
ic_action(struct cam_sim *sim, union ccb *ccb)
{
     isc_session_t	*sp = cam_sim_softc(sim);
     struct ccb_hdr	*ccb_h = &ccb->ccb_h;

     debug_called(8);

     ccb_h->spriv_ptr0 = sp;
     sdebug(4, "func_code=0x%x flags=0x%x status=0x%x target=%d lun=%d retry_count=%d timeout=%d",
	   ccb_h->func_code, ccb->ccb_h.flags, ccb->ccb_h.status,
	   ccb->ccb_h.target_id, ccb->ccb_h.target_lun, 
	   ccb->ccb_h.retry_count, ccb_h->timeout);
     if(sp == NULL) {
	  xdebug("sp == NULL! cannot happen");
	  return;
     }	  
     switch(ccb_h->func_code) {
     case XPT_PATH_INQ:
	  _inq(sim, ccb);
	  break;

     case XPT_RESET_BUS: // (can just be a stub that does nothing and completes)
     {
	  struct ccb_pathinq *cpi = &ccb->cpi;

	  debug(3, "XPT_RESET_BUS");
	  cpi->ccb_h.status = CAM_REQ_CMP;
	  break;
     }

     case XPT_SCSI_IO: 
     {
	  struct ccb_scsiio* csio = &ccb->csio;

	  debug(4, "XPT_SCSI_IO cmd=0x%x", csio->cdb_io.cdb_bytes[0]);
	  if(sp == NULL) {
	       ccb_h->status = CAM_REQ_INVALID; //CAM_NO_NEXUS;
	       debug(4, "xpt_done.status=%d", ccb_h->status);
	       break;
	  }
	  if(ccb_h->target_lun == CAM_LUN_WILDCARD) {
	       debug(3, "target=%d: bad lun (-1)", ccb_h->target_id);
	       ccb_h->status = CAM_LUN_INVALID;
	       break;
	  }
	  if(_scsi_encap(sim, ccb) != 0)
	       return;
	  break;
     }
 
     case XPT_CALC_GEOMETRY:
     {
	  struct	ccb_calc_geometry *ccg;

	  ccg = &ccb->ccg;
	  debug(4, "sid=%d target=%d lun=%d XPT_CALC_GEOMETRY vsize=%jd bsize=%d",
		sp->sid, ccb->ccb_h.target_id, ccb->ccb_h.target_lun,
		ccg->volume_size, ccg->block_size);
	  if(ccg->block_size == 0 ||
	     (ccg->volume_size < ccg->block_size)) {
	       // print error message  ...
	       /* XXX: what error is appropiate? */
	       break;
	  } 
	  else {
	       int	lun, *off, boff;

	       lun = ccb->ccb_h.target_lun;
	       if(lun > ISCSI_MAX_LUNS) {
		    // XXX: 
		    xdebug("lun %d > ISCSI_MAX_LUNS!\n", lun);
		    lun %= ISCSI_MAX_LUNS;
	       }
	       off = &sp->target_lun[lun / (sizeof(int)*8)];
	       boff = BIT(lun % (sizeof(int)*8));
	       debug(4, "sp->target_nluns=%d *off=%x boff=%x",
		     sp->target_nluns, *off, boff);

	       if((*off & boff) == 0) {
		    sp->target_nluns++;
		    *off |= boff;
	       }
	       cam_calc_geometry(ccg, /*extended*/1);
	  }
	  break;
     }

     case XPT_GET_TRAN_SETTINGS:
     default:
	  ccb_h->status = CAM_REQ_INVALID;
	  break;
     }
#if __FreeBSD_version < 700000
     XPT_DONE(sp, ccb);
#else
     xpt_done(ccb);
#endif
     return;
}
Esempio n. 8
0
static void hpt_poll(struct cam_sim *sim)
{
	hpt_pci_intr(cam_sim_softc(sim));
}
Esempio n. 9
0
static void
wds_poll(struct cam_sim * sim)
{
	wds_intr((struct wds *)cam_sim_softc(sim));
}
Esempio n. 10
0
static void
tws_action(struct cam_sim *sim, union ccb *ccb)
{
    struct tws_softc *sc = (struct tws_softc *)cam_sim_softc(sim);


    switch( ccb->ccb_h.func_code ) {
        case XPT_SCSI_IO:   
        {
            if ( tws_execute_scsi(sc, ccb) ) 
                TWS_TRACE_DEBUG(sc, "execute scsi failed", 0, 0);
            break;
        }
        case XPT_ABORT:
        {
            TWS_TRACE_DEBUG(sc, "abort i/o", 0, 0);
            ccb->ccb_h.status = CAM_UA_ABORT;
            xpt_done(ccb);
            break;
        }
        case XPT_RESET_BUS:
        {
            TWS_TRACE_DEBUG(sc, "reset bus", sim, ccb);
            break;
        }
        case XPT_SET_TRAN_SETTINGS:
        {
            TWS_TRACE_DEBUG(sc, "set tran settings", sim, ccb);
            ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
            xpt_done(ccb);

            break;
        }
        case XPT_GET_TRAN_SETTINGS:
        {
            TWS_TRACE_DEBUG(sc, "get tran settings", sim, ccb);

#if (__FreeBSD_version >= 700000 )
            ccb->cts.protocol = PROTO_SCSI;
            ccb->cts.protocol_version = SCSI_REV_2;
            ccb->cts.transport = XPORT_SPI;
            ccb->cts.transport_version = 2;

            ccb->cts.xport_specific.spi.valid = CTS_SPI_VALID_DISC;
            ccb->cts.xport_specific.spi.flags = CTS_SPI_FLAGS_DISC_ENB;
            ccb->cts.proto_specific.scsi.valid = CTS_SCSI_VALID_TQ;
            ccb->cts.proto_specific.scsi.flags = CTS_SCSI_FLAGS_TAG_ENB;
#else
            ccb->cts.valid = (CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID);
            ccb->cts.flags &= ~(CCB_TRANS_DISC_ENB | CCB_TRANS_TAG_ENB);
#endif
            ccb->ccb_h.status = CAM_REQ_CMP;
            xpt_done(ccb);

            break;
        }
        case XPT_CALC_GEOMETRY:
        {
            TWS_TRACE_DEBUG(sc, "calc geometry(ccb,block-size)", ccb, 
                                          ccb->ccg.block_size);
            cam_calc_geometry(&ccb->ccg, 1/* extended */);
            xpt_done(ccb);

            break;
        }
        case XPT_PATH_INQ:
        {
            TWS_TRACE_DEBUG(sc, "path inquiry", sim, ccb);
            ccb->cpi.version_num = 1;
            ccb->cpi.hba_inquiry = 0;
            ccb->cpi.target_sprt = 0;
            ccb->cpi.hba_misc = 0;
            ccb->cpi.hba_eng_cnt = 0;
            ccb->cpi.max_target = TWS_MAX_NUM_UNITS;
            ccb->cpi.max_lun = TWS_MAX_NUM_LUNS - 1;
            ccb->cpi.unit_number = cam_sim_unit(sim);
            ccb->cpi.bus_id = cam_sim_bus(sim);
            ccb->cpi.initiator_id = TWS_SCSI_INITIATOR_ID;
            ccb->cpi.base_transfer_speed = 6000000;
            strncpy(ccb->cpi.sim_vid, "FreeBSD", SIM_IDLEN);
            strncpy(ccb->cpi.hba_vid, "3ware", HBA_IDLEN);
            strncpy(ccb->cpi.dev_name, cam_sim_name(sim), DEV_IDLEN);
#if (__FreeBSD_version >= 700000 )
            ccb->cpi.transport = XPORT_SPI;
            ccb->cpi.transport_version = 2;
            ccb->cpi.protocol = PROTO_SCSI;
            ccb->cpi.protocol_version = SCSI_REV_2;
            ccb->cpi.maxio = TWS_MAX_IO_SIZE;
#endif
            ccb->ccb_h.status = CAM_REQ_CMP;
            xpt_done(ccb);

            break;
        }
        default:
            TWS_TRACE_DEBUG(sc, "default", sim, ccb);
            ccb->ccb_h.status = CAM_REQ_INVALID;
            xpt_done(ccb);
            break;
    }
}
Esempio n. 11
0
static void
wds_scsi_io(struct cam_sim * sim, struct ccb_scsiio * csio)
{
	int	 unit = cam_sim_unit(sim);
	struct	 wds *wp;
	struct	 ccb_hdr *ccb_h;
	struct	 wds_req *r;
	int	 base;
	u_int8_t c;
	int	 error;
	int	 n;

	wp = (struct wds *)cam_sim_softc(sim);
	ccb_h = &csio->ccb_h;

	DBG(DBX "wds%d: cmd TARG=%d LUN=%d\n", unit, ccb_h->target_id,
	    ccb_h->target_lun);

	if (ccb_h->target_id > 7 || ccb_h->target_id == WDS_HBA_ID) {
		ccb_h->status = CAM_TID_INVALID;
		xpt_done((union ccb *) csio);
		return;
	}
	if (ccb_h->target_lun > 7) {
		ccb_h->status = CAM_LUN_INVALID;
		xpt_done((union ccb *) csio);
		return;
	}
	if (csio->dxfer_len > BUFSIZ) {
		ccb_h->status = CAM_REQ_TOO_BIG;
		xpt_done((union ccb *) csio);
		return;
	}
	if (ccb_h->flags & (CAM_CDB_PHYS | CAM_SCATTER_VALID | CAM_DATA_PHYS)) {
		/* don't support these */
		ccb_h->status = CAM_REQ_INVALID;
		xpt_done((union ccb *) csio);
		return;
	}
	base = wp->addr;

	/*
	 * this check is mostly for debugging purposes,
	 * "can't happen" normally.
	 */
	if(wp->want_wdsr) {
		DBG(DBX "wds%d: someone already waits for buffer\n", unit);
		smallog('b');
		n = xpt_freeze_simq(sim, /* count */ 1);
		smallog('0'+n);
		ccb_h->status = CAM_REQUEUE_REQ;
		xpt_done((union ccb *) csio);
		return;
	}

	r = wdsr_alloc(wp);
	if (r == NULL) {
		device_printf(wp->dev, "no request slot available!\n");
		wp->want_wdsr = 1;
		n = xpt_freeze_simq(sim, /* count */ 1);
		smallog2('f', '0'+n);
		ccb_h->status = CAM_REQUEUE_REQ;
		xpt_done((union ccb *) csio);
		return;
	}

	ccb_h->ccb_wdsr = (void *) r;
	r->ccb = (union ccb *) csio;

	switch (error = frag_alloc(wp, csio->dxfer_len, &r->buf, &r->mask)) {
	case CAM_REQ_CMP:
		break;
	case CAM_REQUEUE_REQ:
		DBG(DBX "wds%d: no data buffer available\n", unit);
		wp->want_wdsr = 1;
		n = xpt_freeze_simq(sim, /* count */ 1);
		smallog2('f', '0'+n);
		wdsr_ccb_done(wp, r, r->ccb, CAM_REQUEUE_REQ);
		return;
	default:
		DBG(DBX "wds%d: request is too big\n", unit);
		wdsr_ccb_done(wp, r, r->ccb, error);
		break;
	}

	ccb_h->status |= CAM_SIM_QUEUED;
	r->flags &= ~WR_DONE;

	scsi_ulto3b(WDSTOPHYS(wp, &r->cmd), wp->dx->ombs[r->ombn].addr);

	bzero(&r->cmd, sizeof r->cmd);
	r->cmd.cmd = WDSX_SCSICMD;
	r->cmd.targ = (ccb_h->target_id << 5) | ccb_h->target_lun;

	if (ccb_h->flags & CAM_CDB_POINTER)
		bcopy(csio->cdb_io.cdb_ptr, &r->cmd.scb,
		      csio->cdb_len < 12 ? csio->cdb_len : 12);
	else
		bcopy(csio->cdb_io.cdb_bytes, &r->cmd.scb,
		      csio->cdb_len < 12 ? csio->cdb_len : 12);

	scsi_ulto3b(csio->dxfer_len, r->cmd.len);

	if (csio->dxfer_len > 0
	 && (ccb_h->flags & CAM_DIR_MASK) == CAM_DIR_OUT) {
		/* we already rejected physical or scattered addresses */
		bcopy(csio->data_ptr, r->buf, csio->dxfer_len);
	}
	scsi_ulto3b(csio->dxfer_len ? WDSTOPHYS(wp, r->buf) : 0, r->cmd.data);

	if ((ccb_h->flags & CAM_DIR_MASK) == CAM_DIR_IN)
		r->cmd.write = 0x80;
	else
		r->cmd.write = 0x00;

	scsi_ulto3b(0, r->cmd.next);

	outb(base + WDS_HCR, WDSH_IRQEN | WDSH_DRQEN);

	c = WDSC_MSTART(r->ombn);

	if (wds_cmd(base, &c, sizeof c) != 0) {
		device_printf(wp->dev, "unable to start outgoing mbox\n");
		wp->dx->ombs[r->ombn].stat = 0;
		wdsr_ccb_done(wp, r, r->ccb, CAM_RESRC_UNAVAIL);
		return;
	}
	DBG(DBX "wds%d: enqueued cmd 0x%x, r=%p\n", unit,
	    r->cmd.scb[0] & 0xFF, r);

	smallog3('+', ccb_h->target_id + '0', ccb_h->target_lun + '0');
}
Esempio n. 12
0
/********************************************************************************
 * Handle a request for action from CAM
 */
static void
amr_cam_action(struct cam_sim *sim, union ccb *ccb)
{
    struct amr_softc	*sc = cam_sim_softc(sim);

    switch(ccb->ccb_h.func_code) {

    /*
     * Perform SCSI I/O to a physical device.
     */
    case XPT_SCSI_IO:
    {
	struct ccb_hdr		*ccbh = &ccb->ccb_h;
	struct ccb_scsiio	*csio = &ccb->csio;

	/* Validate the CCB */
	ccbh->status = CAM_REQ_INPROG;

	/* check the CDB length */
	if (csio->cdb_len > AMR_MAX_EXTCDB_LEN)
	    ccbh->status = CAM_REQ_CMP_ERR;

	if ((csio->cdb_len > AMR_MAX_CDB_LEN) && (sc->support_ext_cdb == 0 ))
	    ccbh->status = CAM_REQ_CMP_ERR;

	/* check that the CDB pointer is not to a physical address */
	if ((ccbh->flags & CAM_CDB_POINTER) && (ccbh->flags & CAM_CDB_PHYS))
	    ccbh->status = CAM_REQ_CMP_ERR;

	/* if there is data transfer, it must be to/from a virtual address */
	if ((ccbh->flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
	    if (ccbh->flags & CAM_DATA_PHYS)		/* we can't map it */
		ccbh->status = CAM_REQ_CMP_ERR;		
	    if (ccbh->flags & CAM_SCATTER_VALID)	/* we want to do the s/g setup */
		ccbh->status = CAM_REQ_CMP_ERR;
	}

	/*
	 * If the command is to a LUN other than 0, fail it.
	 * This is probably incorrect, but during testing the firmware did not
	 * seem to respect the LUN field, and thus devices appear echoed.
	 */
	if (csio->ccb_h.target_lun != 0)
	    ccbh->status = CAM_REQ_CMP_ERR;

	/* if we're happy with the request, queue it for attention */
	if (ccbh->status == CAM_REQ_INPROG) {

	    /* save the channel number in the ccb */
	    csio->ccb_h.sim_priv.entries[0].field = cam_sim_bus(sim);

	    amr_enqueue_ccb(sc, ccb);
	    amr_startio(sc);
	    return;
	}
	break;
    }

    case XPT_CALC_GEOMETRY:
    {
	struct    ccb_calc_geometry *ccg = &ccb->ccg;
	u_int32_t size_in_mb;
	u_int32_t secs_per_cylinder;

	size_in_mb = ccg->volume_size / ((1024L * 1024L) / ccg->block_size);

	if (size_in_mb > 1024) {
	    ccg->heads = 255;
	    ccg->secs_per_track = 63;
	} else {
	    ccg->heads = 64;
	    ccg->secs_per_track = 32;
	}
	secs_per_cylinder = ccg->heads * ccg->secs_per_track;
	ccg->cylinders = ccg->volume_size / secs_per_cylinder;
	ccb->ccb_h.status = CAM_REQ_CMP;
	break;
    }

    /*
     * Return path stats.  Some of these should probably be
     * amended.
     */
    case XPT_PATH_INQ:
    {
	struct ccb_pathinq      *cpi = & ccb->cpi;

	debug(3, "XPT_PATH_INQ");
	cpi->version_num = 1;           /* XXX??? */
	cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE|PI_WIDE_16;
	cpi->target_sprt = 0;
	cpi->hba_misc = PIM_NOBUSRESET;
	cpi->hba_eng_cnt = 0;
	cpi->max_target = AMR_MAX_TARGETS;
	cpi->max_lun = 0 /* AMR_MAX_LUNS*/;
	cpi->initiator_id = 7;          /* XXX variable? */
	strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
	strncpy(cpi->hba_vid, "LSI", HBA_IDLEN);
	strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
	cpi->unit_number = cam_sim_unit(sim);
	cpi->bus_id = cam_sim_bus(sim);
	cpi->base_transfer_speed = 132 * 1024;  /* XXX get from controller? */
	cpi->ccb_h.status = CAM_REQ_CMP;

	break;
    }

    case XPT_RESET_BUS:
    {
	struct ccb_pathinq	*cpi = & ccb->cpi;

	debug(1, "XPT_RESET_BUS");
	cpi->ccb_h.status = CAM_REQ_CMP;
	break;
    }

    case XPT_RESET_DEV:
    {
	debug(1, "XPT_RESET_DEV");
	ccb->ccb_h.status = CAM_REQ_CMP;
	break;
    }

    case XPT_GET_TRAN_SETTINGS:
    {
	struct ccb_trans_settings	*cts;

	debug(3, "XPT_GET_TRAN_SETTINGS");

	cts = &(ccb->cts);

	if ((cts->flags & CCB_TRANS_USER_SETTINGS) == 0) {
		ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
		break;
        }

	cts->flags = CCB_TRANS_DISC_ENB|CCB_TRANS_TAG_ENB;
	cts->bus_width = MSG_EXT_WDTR_BUS_32_BIT;
	cts->sync_period = 6;   /* 40MHz how wide is this bus? */
	cts->sync_offset = 31;  /* How to extract this from board? */

	cts->valid = CCB_TRANS_SYNC_RATE_VALID
	    | CCB_TRANS_SYNC_OFFSET_VALID
	    | CCB_TRANS_BUS_WIDTH_VALID
	    | CCB_TRANS_DISC_VALID
	    | CCB_TRANS_TQ_VALID;
	ccb->ccb_h.status = CAM_REQ_CMP;
	break;
    }

    case XPT_SET_TRAN_SETTINGS:
	debug(3, "XPT_SET_TRAN_SETTINGS");
	ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
	break;


    /*
     * Reject anything else as unsupported.
     */
    default:
	/* we can't do this */
	ccb->ccb_h.status = CAM_REQ_INVALID;
	break;
    }
    xpt_done(ccb);
}
Esempio n. 13
0
static void
ahbaction(struct cam_sim *sim, union ccb *ccb)
{
	struct	ahb_softc *ahb;

	CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("ahbaction\n"));
	
	ahb = (struct ahb_softc *)cam_sim_softc(sim);
	
	switch (ccb->ccb_h.func_code) {
	/* Common cases first */
	case XPT_SCSI_IO:	/* Execute the requested I/O operation */
	{
		struct ecb *ecb;
		struct hardware_ecb *hecb;

		/*
		 * get an ecb to use.
		 */
		if ((ecb = ahbecbget(ahb)) == NULL) {
			/* Should never occur */
			panic("Failed to get an ecb");
		}

		/*
		 * So we can find the ECB when an abort is requested
		 */
		ecb->ccb = ccb;
		ccb->ccb_h.ccb_ecb_ptr = ecb;
		ccb->ccb_h.ccb_ahb_ptr = ahb;

		/*
		 * Put all the arguments for the xfer in the ecb
		 */
		hecb = &ecb->hecb;
		hecb->opcode = ECBOP_INITIATOR_SCSI_CMD;
		hecb->flag_word1 = FW1_AUTO_REQUEST_SENSE
				 | FW1_ERR_STATUS_BLK_ONLY;
		hecb->flag_word2 = ccb->ccb_h.target_lun
				 | FW2_NO_RETRY_ON_BUSY;
		if ((ccb->ccb_h.flags & CAM_TAG_ACTION_VALID) != 0) {
			hecb->flag_word2 |= FW2_TAG_ENB
					 | ((ccb->csio.tag_action & 0x3)
					    << FW2_TAG_TYPE_SHIFT);
		}
		if ((ccb->ccb_h.flags & CAM_DIS_DISCONNECT) != 0)
			hecb->flag_word2 |= FW2_DISABLE_DISC;
		hecb->sense_len = ccb->csio.sense_len;
		hecb->cdb_len = ccb->csio.cdb_len;
		if ((ccb->ccb_h.flags & CAM_CDB_POINTER) != 0) {
			if ((ccb->ccb_h.flags & CAM_CDB_PHYS) == 0) {
				bcopy(ccb->csio.cdb_io.cdb_ptr,
				      hecb->cdb, hecb->cdb_len);
			} else {
				/* I guess I could map it in... */
				ccb->ccb_h.status = CAM_REQ_INVALID;
				ahbecbfree(ahb, ecb);
				xpt_done(ccb);
				return;
			}
		} else {
			bcopy(ccb->csio.cdb_io.cdb_bytes,
			      hecb->cdb, hecb->cdb_len);
		}

		/*
		 * If we have any data to send with this command,
		 * map it into bus space.
		 */
		if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
			if ((ccb->ccb_h.flags & CAM_SCATTER_VALID) == 0) {
				/*
				 * We've been given a pointer
				 * to a single buffer.
				 */
				if ((ccb->ccb_h.flags & CAM_DATA_PHYS)==0) {
					int s;
					int error;

					s = splsoftvm();
					error = bus_dmamap_load(
					    ahb->buffer_dmat,
					    ecb->dmamap,
					    ccb->csio.data_ptr,
					    ccb->csio.dxfer_len,
					    ahbexecuteecb,
					    ecb, /*flags*/0);
					if (error == EINPROGRESS) {
						/*
						 * So as to maintain ordering,
						 * freeze the controller queue
						 * until our mapping is
						 * returned.
						 */
						xpt_freeze_simq(ahb->sim, 1);
						ccb->ccb_h.status |=
						    CAM_RELEASE_SIMQ;
					}
					splx(s);
				} else {
					struct bus_dma_segment seg; 

					/* Pointer to physical buffer */
					seg.ds_addr =
					    (bus_addr_t)ccb->csio.data_ptr;
					seg.ds_len = ccb->csio.dxfer_len;
					ahbexecuteecb(ecb, &seg, 1, 0);
				}
			} else {
				struct bus_dma_segment *segs;

				if ((ccb->ccb_h.flags & CAM_DATA_PHYS) != 0)
					panic("ahbaction - Physical segment "
					      "pointers unsupported");

				if ((ccb->ccb_h.flags & CAM_SG_LIST_PHYS) == 0)
					panic("btaction - Virtual segment "
					      "addresses unsupported");

				/* Just use the segments provided */
				segs = (struct bus_dma_segment *)
				    ccb->csio.data_ptr;
				ahbexecuteecb(ecb, segs, ccb->csio.sglist_cnt,
					     0);
			}
		} else {
			ahbexecuteecb(ecb, NULL, 0, 0);
		}
		break;
	}
	case XPT_EN_LUN:		/* Enable LUN as a target */
	case XPT_TARGET_IO:		/* Execute target I/O request */
	case XPT_ACCEPT_TARGET_IO:	/* Accept Host Target Mode CDB */
	case XPT_CONT_TARGET_IO:	/* Continue Host Target I/O Connection*/
	case XPT_ABORT:			/* Abort the specified CCB */
		/* XXX Implement */
		ccb->ccb_h.status = CAM_REQ_INVALID;
		xpt_done(ccb);
		break;
	case XPT_SET_TRAN_SETTINGS:
	{
		ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
		xpt_done(ccb);
		break;
	}
	case XPT_GET_TRAN_SETTINGS:
	/* Get default/user set transfer settings for the target */
	{
		struct	ccb_trans_settings *cts = &ccb->cts;
		u_int	target_mask = 0x01 << ccb->ccb_h.target_id;
		struct ccb_trans_settings_scsi *scsi =
		    &cts->proto_specific.scsi;
		struct ccb_trans_settings_spi *spi =
		    &cts->xport_specific.spi;

		if (cts->type == CTS_TYPE_USER_SETTINGS) {
			cts->protocol = PROTO_SCSI;
			cts->protocol_version = SCSI_REV_2;
			cts->transport = XPORT_SPI;
			cts->transport_version = 2;

			scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
			spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
			if ((ahb->disc_permitted & target_mask) != 0)
				spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
			if ((ahb->tags_permitted & target_mask) != 0)
				scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
			spi->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
			spi->sync_period = 25; /* 10MHz */

			if (spi->sync_period != 0)
				spi->sync_offset = 15;

			spi->valid = CTS_SPI_VALID_SYNC_RATE
				   | CTS_SPI_VALID_SYNC_OFFSET
				   | CTS_SPI_VALID_BUS_WIDTH
				   | CTS_SPI_VALID_DISC;
			scsi->valid = CTS_SCSI_VALID_TQ;
			ccb->ccb_h.status = CAM_REQ_CMP;
		} else {
			ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
		}
		xpt_done(ccb);
		break;
	}
	case XPT_RESET_DEV:	/* Bus Device Reset the specified SCSI device */
	{
		int i;
		int s;

		s = splcam();
		ahb->immed_cmd = IMMED_RESET;
		ahbqueuembox(ahb, IMMED_RESET, ATTN_IMMED|ccb->ccb_h.target_id);
		/* Poll for interrupt completion */
		for (i = 1000; ahb->immed_cmd != 0 && i != 0; i--) {
			DELAY(1000);
			ahbintr(cam_sim_softc(sim));
		}
		splx(s);
		break;
	}
	case XPT_CALC_GEOMETRY:
	{
		cam_calc_geometry(&ccb->ccg, ahb->extended_trans); 
		xpt_done(ccb);
		break;
	}
	case XPT_RESET_BUS:		/* Reset the specified SCSI bus */
	{
		int i;

		ahb->immed_cmd = IMMED_RESET;
		ahbqueuembox(ahb, IMMED_RESET, ATTN_IMMED|ahb->scsi_id);
		/* Poll for interrupt completion */
		for (i = 1000; ahb->immed_cmd != 0 && i != 0; i--)
			DELAY(1000);
		ccb->ccb_h.status = CAM_REQ_CMP;
		xpt_done(ccb);
		break;
	}
	case XPT_TERM_IO:		/* Terminate the I/O process */
		/* XXX Implement */
		ccb->ccb_h.status = CAM_REQ_INVALID;
		xpt_done(ccb);
		break;
	case XPT_PATH_INQ:		/* Path routing inquiry */
	{
		struct ccb_pathinq *cpi = &ccb->cpi;
		
		cpi->version_num = 1; /* XXX??? */
		cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE;
		cpi->target_sprt = 0;
		cpi->hba_misc = 0;
		cpi->hba_eng_cnt = 0;
		cpi->max_target = 7;
		cpi->max_lun = 7;
		cpi->initiator_id = ahb->scsi_id;
		cpi->bus_id = cam_sim_bus(sim);
		cpi->base_transfer_speed = 3300;
		strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
		strncpy(cpi->hba_vid, "Adaptec", HBA_IDLEN);
		strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
		cpi->unit_number = cam_sim_unit(sim);
                cpi->transport = XPORT_SPI;
                cpi->transport_version = 2;
                cpi->protocol = PROTO_SCSI;
                cpi->protocol_version = SCSI_REV_2;
		cpi->ccb_h.status = CAM_REQ_CMP;
		xpt_done(ccb);
		break;
	}
#if 0
	/* Need these??? */
        case XPT_IMMED_NOTIFY:		/* Notify Host Target driver of event */
        case XPT_NOTIFY_ACK:		/* Acknowledgement of event */
#endif
	default:
		ccb->ccb_h.status = CAM_REQ_INVALID;
		xpt_done(ccb);
		break;
	}
}
Esempio n. 14
0
static void
adv_execute_ccb(void *arg, bus_dma_segment_t *dm_segs,
		int nsegments, int error)
{
	struct	ccb_scsiio *csio;
	struct	ccb_hdr *ccb_h;
	struct	cam_sim *sim;
        struct	adv_softc *adv;
	struct	adv_ccb_info *cinfo;
	struct	adv_scsi_q scsiq;
	struct	adv_sg_head sghead;

	csio = (struct ccb_scsiio *)arg;
	ccb_h = &csio->ccb_h;
	sim = xpt_path_sim(ccb_h->path);
	adv = (struct adv_softc *)cam_sim_softc(sim);
	cinfo = (struct adv_ccb_info *)csio->ccb_h.ccb_cinfo_ptr;
	if (!dumping)
		mtx_assert(&adv->lock, MA_OWNED);

	/*
	 * Setup our done routine to release the simq on
	 * the next ccb that completes.
	 */
	if ((adv->state & ADV_BUSDMA_BLOCK) != 0)
		adv->state |= ADV_BUSDMA_BLOCK_CLEARED;

	if ((ccb_h->flags & CAM_CDB_POINTER) != 0) {
		if ((ccb_h->flags & CAM_CDB_PHYS) == 0) {
			/* XXX Need phystovirt!!!! */
			/* How about pmap_kenter??? */
			scsiq.cdbptr = csio->cdb_io.cdb_ptr;
		} else {
			scsiq.cdbptr = csio->cdb_io.cdb_ptr;
		}
	} else {
		scsiq.cdbptr = csio->cdb_io.cdb_bytes;
	}
	/*
	 * Build up the request
	 */
	scsiq.q1.status = 0;
	scsiq.q1.q_no = 0;
	scsiq.q1.cntl = 0;
	scsiq.q1.sg_queue_cnt = 0;
	scsiq.q1.target_id = ADV_TID_TO_TARGET_MASK(ccb_h->target_id);
	scsiq.q1.target_lun = ccb_h->target_lun;
	scsiq.q1.sense_len = csio->sense_len;
	scsiq.q1.extra_bytes = 0;
	scsiq.q2.ccb_index = cinfo - adv->ccb_infos;
	scsiq.q2.target_ix = ADV_TIDLUN_TO_IX(ccb_h->target_id,
					      ccb_h->target_lun);
	scsiq.q2.flag = 0;
	scsiq.q2.cdb_len = csio->cdb_len;
	if ((ccb_h->flags & CAM_TAG_ACTION_VALID) != 0)
		scsiq.q2.tag_code = csio->tag_action;
	else
		scsiq.q2.tag_code = 0;
	scsiq.q2.vm_id = 0;

	if (nsegments != 0) {
		bus_dmasync_op_t op;

		scsiq.q1.data_addr = dm_segs->ds_addr;
                scsiq.q1.data_cnt = dm_segs->ds_len;
		if (nsegments > 1) {
			scsiq.q1.cntl |= QC_SG_HEAD;
			sghead.entry_cnt
			    = sghead.entry_to_copy
			    = nsegments;
			sghead.res = 0;
			sghead.sg_list = adv_fixup_dmasegs(adv, dm_segs);
			scsiq.sg_head = &sghead;
		} else {
			scsiq.sg_head = NULL;
		}
		if ((ccb_h->flags & CAM_DIR_MASK) == CAM_DIR_IN)
			op = BUS_DMASYNC_PREREAD;
		else
			op = BUS_DMASYNC_PREWRITE;
		bus_dmamap_sync(adv->buffer_dmat, cinfo->dmamap, op);
	} else {
		scsiq.q1.data_addr = 0;	
		scsiq.q1.data_cnt = 0;
		scsiq.sg_head = NULL;
	}

	/*
	 * Last time we need to check if this SCB needs to
	 * be aborted.
	 */             
	if (ccb_h->status != CAM_REQ_INPROG) {
		if (nsegments != 0)
			bus_dmamap_unload(adv->buffer_dmat, cinfo->dmamap);
		adv_clear_state(adv, (union ccb *)csio);
		adv_free_ccb_info(adv, cinfo);
		xpt_done((union ccb *)csio);
		return;
	}

	if (adv_execute_scsi_queue(adv, &scsiq, csio->dxfer_len) != 0) {
		/* Temporary resource shortage */
		adv_set_state(adv, ADV_RESOURCE_SHORTAGE);
		if (nsegments != 0)
			bus_dmamap_unload(adv->buffer_dmat, cinfo->dmamap);
		csio->ccb_h.status = CAM_REQUEUE_REQ;
		adv_clear_state(adv, (union ccb *)csio);
		adv_free_ccb_info(adv, cinfo);
		xpt_done((union ccb *)csio);
		return;
	}
	cinfo->state |= ACCB_ACTIVE;
	ccb_h->status |= CAM_SIM_QUEUED;
	LIST_INSERT_HEAD(&adv->pending_ccbs, ccb_h, sim_links.le);
	/* Schedule our timeout */
	callout_reset_sbt(&cinfo->timer, SBT_1MS * ccb_h->timeout, 0,
	    adv_timeout, csio, 0);
}
Esempio n. 15
0
static void
ataaction(struct cam_sim *sim, union ccb *ccb)
{
	device_t dev, parent;
	struct ata_channel *ch;

	CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("ataaction func_code=%x\n",
	    ccb->ccb_h.func_code));

	ch = (struct ata_channel *)cam_sim_softc(sim);
	dev = ch->dev;
	switch (ccb->ccb_h.func_code) {
	/* Common cases first */
	case XPT_ATA_IO:	/* Execute the requested I/O operation */
	case XPT_SCSI_IO:
		if (ata_check_ids(dev, ccb))
			return;
		if ((ch->devices & ((ATA_ATA_MASTER | ATA_ATAPI_MASTER)
		    << ccb->ccb_h.target_id)) == 0) {
			ccb->ccb_h.status = CAM_SEL_TIMEOUT;
			break;
		}
		if (ch->running)
			device_printf(dev, "already running!\n");
		if (ccb->ccb_h.func_code == XPT_ATA_IO &&
		    (ccb->ataio.cmd.flags & CAM_ATAIO_CONTROL) &&
		    (ccb->ataio.cmd.control & ATA_A_RESET)) {
			struct ata_res *res = &ccb->ataio.res;
			
			bzero(res, sizeof(*res));
			if (ch->devices & (ATA_ATA_MASTER << ccb->ccb_h.target_id)) {
				res->lba_high = 0;
				res->lba_mid = 0;
			} else {
				res->lba_high = 0xeb;
				res->lba_mid = 0x14;
			}
			ccb->ccb_h.status = CAM_REQ_CMP;
			break;
		}
		ata_cam_begin_transaction(dev, ccb);
		return;
	case XPT_EN_LUN:		/* Enable LUN as a target */
	case XPT_TARGET_IO:		/* Execute target I/O request */
	case XPT_ACCEPT_TARGET_IO:	/* Accept Host Target Mode CDB */
	case XPT_CONT_TARGET_IO:	/* Continue Host Target I/O Connection*/
	case XPT_ABORT:			/* Abort the specified CCB */
		/* XXX Implement */
		ccb->ccb_h.status = CAM_REQ_INVALID;
		break;
	case XPT_SET_TRAN_SETTINGS:
	{
		struct	ccb_trans_settings *cts = &ccb->cts;
		struct	ata_cam_device *d; 

		if (ata_check_ids(dev, ccb))
			return;
		if (cts->type == CTS_TYPE_CURRENT_SETTINGS)
			d = &ch->curr[ccb->ccb_h.target_id];
		else
			d = &ch->user[ccb->ccb_h.target_id];
		if (ch->flags & ATA_SATA) {
			if (cts->xport_specific.sata.valid & CTS_SATA_VALID_REVISION)
				d->revision = cts->xport_specific.sata.revision;
			if (cts->xport_specific.sata.valid & CTS_SATA_VALID_MODE) {
				if (cts->type == CTS_TYPE_CURRENT_SETTINGS) {
					d->mode = ATA_SETMODE(ch->dev,
					    ccb->ccb_h.target_id,
					    cts->xport_specific.sata.mode);
				} else
					d->mode = cts->xport_specific.sata.mode;
			}
			if (cts->xport_specific.sata.valid & CTS_SATA_VALID_BYTECOUNT)
				d->bytecount = min(8192, cts->xport_specific.sata.bytecount);
			if (cts->xport_specific.sata.valid & CTS_SATA_VALID_ATAPI)
				d->atapi = cts->xport_specific.sata.atapi;
			if (cts->xport_specific.sata.valid & CTS_SATA_VALID_CAPS)
				d->caps = cts->xport_specific.sata.caps;
		} else {
			if (cts->xport_specific.ata.valid & CTS_ATA_VALID_MODE) {
				if (cts->type == CTS_TYPE_CURRENT_SETTINGS) {
					d->mode = ATA_SETMODE(ch->dev,
					    ccb->ccb_h.target_id,
					    cts->xport_specific.ata.mode);
				} else
					d->mode = cts->xport_specific.ata.mode;
			}
			if (cts->xport_specific.ata.valid & CTS_ATA_VALID_BYTECOUNT)
				d->bytecount = cts->xport_specific.ata.bytecount;
			if (cts->xport_specific.ata.valid & CTS_ATA_VALID_ATAPI)
				d->atapi = cts->xport_specific.ata.atapi;
			if (cts->xport_specific.ata.valid & CTS_ATA_VALID_CAPS)
				d->caps = cts->xport_specific.ata.caps;
		}
		ccb->ccb_h.status = CAM_REQ_CMP;
		break;
	}
	case XPT_GET_TRAN_SETTINGS:
	{
		struct	ccb_trans_settings *cts = &ccb->cts;
		struct  ata_cam_device *d;

		if (ata_check_ids(dev, ccb))
			return;
		if (cts->type == CTS_TYPE_CURRENT_SETTINGS)
			d = &ch->curr[ccb->ccb_h.target_id];
		else
			d = &ch->user[ccb->ccb_h.target_id];
		cts->protocol = PROTO_UNSPECIFIED;
		cts->protocol_version = PROTO_VERSION_UNSPECIFIED;
		if (ch->flags & ATA_SATA) {
			cts->transport = XPORT_SATA;
			cts->transport_version = XPORT_VERSION_UNSPECIFIED;
			cts->xport_specific.sata.valid = 0;
			cts->xport_specific.sata.mode = d->mode;
			cts->xport_specific.sata.valid |= CTS_SATA_VALID_MODE;
			cts->xport_specific.sata.bytecount = d->bytecount;
			cts->xport_specific.sata.valid |= CTS_SATA_VALID_BYTECOUNT;
			if (cts->type == CTS_TYPE_CURRENT_SETTINGS) {
				cts->xport_specific.sata.revision =
				    ATA_GETREV(dev, ccb->ccb_h.target_id);
				if (cts->xport_specific.sata.revision != 0xff) {
					cts->xport_specific.sata.valid |=
					    CTS_SATA_VALID_REVISION;
				}
				cts->xport_specific.sata.caps =
				    d->caps & CTS_SATA_CAPS_D;
				if (ch->pm_level) {
					cts->xport_specific.sata.caps |=
					    CTS_SATA_CAPS_H_PMREQ;
				}
				cts->xport_specific.sata.caps &=
				    ch->user[ccb->ccb_h.target_id].caps;
			} else {
				cts->xport_specific.sata.revision = d->revision;
				cts->xport_specific.sata.valid |= CTS_SATA_VALID_REVISION;
				cts->xport_specific.sata.caps = d->caps;
			}
			cts->xport_specific.sata.valid |= CTS_SATA_VALID_CAPS;
			cts->xport_specific.sata.atapi = d->atapi;
			cts->xport_specific.sata.valid |= CTS_SATA_VALID_ATAPI;
		} else {
			cts->transport = XPORT_ATA;
			cts->transport_version = XPORT_VERSION_UNSPECIFIED;
			cts->xport_specific.ata.valid = 0;
			cts->xport_specific.ata.mode = d->mode;
			cts->xport_specific.ata.valid |= CTS_ATA_VALID_MODE;
			cts->xport_specific.ata.bytecount = d->bytecount;
			cts->xport_specific.ata.valid |= CTS_ATA_VALID_BYTECOUNT;
			if (cts->type == CTS_TYPE_CURRENT_SETTINGS) {
				cts->xport_specific.ata.caps =
				    d->caps & CTS_ATA_CAPS_D;
				if (!(ch->flags & ATA_NO_48BIT_DMA))
					cts->xport_specific.ata.caps |=
					    CTS_ATA_CAPS_H_DMA48;
				cts->xport_specific.ata.caps &=
				    ch->user[ccb->ccb_h.target_id].caps;
			} else
				cts->xport_specific.ata.caps = d->caps;
			cts->xport_specific.ata.valid |= CTS_ATA_VALID_CAPS;
			cts->xport_specific.ata.atapi = d->atapi;
			cts->xport_specific.ata.valid |= CTS_ATA_VALID_ATAPI;
		}
		ccb->ccb_h.status = CAM_REQ_CMP;
		break;
	}
	case XPT_RESET_BUS:		/* Reset the specified SCSI bus */
	case XPT_RESET_DEV:	/* Bus Device Reset the specified SCSI device */
		ata_reinit(dev);
		ccb->ccb_h.status = CAM_REQ_CMP;
		break;
	case XPT_TERM_IO:		/* Terminate the I/O process */
		/* XXX Implement */
		ccb->ccb_h.status = CAM_REQ_INVALID;
		break;
	case XPT_PATH_INQ:		/* Path routing inquiry */
	{
		struct ccb_pathinq *cpi = &ccb->cpi;

		parent = device_get_parent(dev);
		cpi->version_num = 1; /* XXX??? */
		cpi->hba_inquiry = PI_SDTR_ABLE;
		cpi->target_sprt = 0;
		cpi->hba_misc = PIM_SEQSCAN | PIM_UNMAPPED;
		cpi->hba_eng_cnt = 0;
		if (ch->flags & ATA_NO_SLAVE)
			cpi->max_target = 0;
		else
			cpi->max_target = 1;
		cpi->max_lun = 0;
		cpi->initiator_id = 0;
		cpi->bus_id = cam_sim_bus(sim);
		if (ch->flags & ATA_SATA)
			cpi->base_transfer_speed = 150000;
		else
			cpi->base_transfer_speed = 3300;
		strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
		strncpy(cpi->hba_vid, "ATA", HBA_IDLEN);
		strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
		cpi->unit_number = cam_sim_unit(sim);
		if (ch->flags & ATA_SATA)
			cpi->transport = XPORT_SATA;
		else
			cpi->transport = XPORT_ATA;
		cpi->transport_version = XPORT_VERSION_UNSPECIFIED;
		cpi->protocol = PROTO_ATA;
		cpi->protocol_version = PROTO_VERSION_UNSPECIFIED;
		cpi->maxio = ch->dma.max_iosize ? ch->dma.max_iosize : DFLTPHYS;
		if (device_get_devclass(device_get_parent(parent)) ==
		    devclass_find("pci")) {
			cpi->hba_vendor = pci_get_vendor(parent);
			cpi->hba_device = pci_get_device(parent);
			cpi->hba_subvendor = pci_get_subvendor(parent);
			cpi->hba_subdevice = pci_get_subdevice(parent);
		}
		cpi->ccb_h.status = CAM_REQ_CMP;
		break;
	}
	default:
		ccb->ccb_h.status = CAM_REQ_INVALID;
		break;
	}
	xpt_done(ccb);
}
Esempio n. 16
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
 */
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 twa_request	*tr;

		if ((sc->twa_state & TWA_STATE_SIMQ_FROZEN) ||
				((tr = twa_get_request(sc)) == NULL)) {
			twa_dbg_dprint(2, sc, "simq frozen/Cannot get request pkt.");
			/*
			 * Freeze the simq to maintain ccb ordering.  The next
			 * ccb that gets completed will unfreeze the simq.
			 */
			twa_disallow_new_requests(sc);
			ccb_h->status |= CAM_REQUEUE_REQ;
			xpt_done(ccb);
			break;
		}
		tr->tr_cmd_pkt_type |= TWA_CMD_PKT_TYPE_EXTERNAL;
		tr->tr_private = ccb;
		tr->tr_callback = twa_complete_io;
		if (twa_execute_scsi(tr, ccb))
			twa_release_request(tr);
		break;
	}

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

	case XPT_RESET_BUS:
		twa_printf(sc, "Reset Bus request from CAM...\n");
		if (twa_reset(sc)) {
			twa_printf(sc, "Reset Bus failed!\n");
			ccb_h->status = CAM_REQ_CMP_ERR;
		}
		else
			ccb_h->status = CAM_REQ_CMP;

		xpt_done(ccb);
		break;

	case XPT_SET_TRAN_SETTINGS:
		twa_dbg_dprint(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;

		twa_dbg_dprint(3, sc, "XPT_GET_TRAN_SETTINGS");
		cts->valid = (CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID);
		cts->flags &= ~(CCB_TRANS_DISC_ENB | CCB_TRANS_TAG_ENB);
		ccb_h->status = CAM_REQ_CMP;
		xpt_done(ccb);
		break;
	}

	case XPT_CALC_GEOMETRY:
	{
		struct ccb_calc_geometry	*geom;

		twa_dbg_dprint(3, sc, "XPT_CALC_GEOMETRY request");
		geom = &ccb->ccg;

		if (geom->volume_size > 0x200000) /* 1 GB */ {
			geom->heads = 255;
			geom->secs_per_track = 63;
		} else {
			geom->heads = 64;
			geom->secs_per_track = 32;
		}
		geom->cylinders = geom->volume_size /
					(geom->heads * geom->secs_per_track);
		ccb_h->status = CAM_REQ_CMP;
		xpt_done(ccb);
		break;
	}

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

		twa_dbg_dprint(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 = TWA_MAX_UNITS;
		path_inq->max_lun = 0;
		path_inq->unit_number = cam_sim_unit(sim);
		path_inq->bus_id = cam_sim_bus(sim);
		path_inq->initiator_id = 12;
		path_inq->base_transfer_speed = 100000;
		strncpy(path_inq->sim_vid, "FreeBSD", SIM_IDLEN);
		strncpy(path_inq->hba_vid, "3ware", HBA_IDLEN);
		strncpy(path_inq->dev_name, cam_sim_name(sim), DEV_IDLEN);
		ccb_h->status = CAM_REQ_CMP;
		xpt_done(ccb);
		break;
	}

	default:
		twa_dbg_dprint(3, sc, "func_code = %x", ccb_h->func_code);
		ccb_h->status = CAM_REQ_INVALID;
		xpt_done(ccb);
		break;
	}
}
Esempio n. 17
0
static void
aac_cam_action(struct cam_sim *sim, union ccb *ccb)
{
    struct	aac_cam *camsc;
    struct	aac_softc *sc;
    struct	aac_srb32 *srb;
    struct	aac_fib *fib;
    struct	aac_command *cm;

    camsc = (struct aac_cam *)cam_sim_softc(sim);
    sc = camsc->inf->aac_sc;
    fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");

    /* Synchronous ops, and ops that don't require communication with the
     * controller */
    switch(ccb->ccb_h.func_code) {
    case XPT_SCSI_IO:
    case XPT_RESET_DEV:
        /* These are handled down below */
        break;
    case XPT_CALC_GEOMETRY:
    {
        struct ccb_calc_geometry *ccg;
        u_int32_t size_mb;
        u_int32_t secs_per_cylinder;

        ccg = &ccb->ccg;
        size_mb = ccg->volume_size /
                  ((1024L * 1024L) / ccg->block_size);
        if (size_mb >= (2 * 1024)) {		/* 2GB */
            ccg->heads = 255;
            ccg->secs_per_track = 63;
        } else if (size_mb >= (1 * 1024)) {	/* 1GB */
            ccg->heads = 128;
            ccg->secs_per_track = 32;
        } else {
            ccg->heads = 64;
            ccg->secs_per_track = 32;
        }
        secs_per_cylinder = ccg->heads * ccg->secs_per_track;
        ccg->cylinders = ccg->volume_size / secs_per_cylinder;

        ccb->ccb_h.status = CAM_REQ_CMP;
        xpt_done(ccb);
        return;
    }
    case XPT_PATH_INQ:
    {
        struct ccb_pathinq *cpi = &ccb->cpi;

        cpi->version_num = 1;
        cpi->hba_inquiry = PI_WIDE_16;
        cpi->target_sprt = 0;

        /*
         * Resetting via the passthrough or parallel bus scan
         * causes problems.
         */
        cpi->hba_misc = PIM_NOBUSRESET | PIM_SEQSCAN;
        cpi->hba_eng_cnt = 0;
        cpi->max_target = camsc->inf->TargetsPerBus;
        cpi->max_lun = 8;	/* Per the controller spec */
        cpi->initiator_id = camsc->inf->InitiatorBusId;
        cpi->bus_id = camsc->inf->BusNumber;
        cpi->base_transfer_speed = 3300;
        strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
        strncpy(cpi->hba_vid, "Adaptec", HBA_IDLEN);
        strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
        cpi->unit_number = cam_sim_unit(sim);
        cpi->transport = XPORT_SPI;
        cpi->transport_version = 2;
        cpi->protocol = PROTO_SCSI;
        cpi->protocol_version = SCSI_REV_2;
        ccb->ccb_h.status = CAM_REQ_CMP;
        xpt_done(ccb);
        return;
    }
    case XPT_GET_TRAN_SETTINGS:
    {
        struct ccb_trans_settings_scsi *scsi =
                &ccb->cts.proto_specific.scsi;
        struct ccb_trans_settings_spi *spi =
                &ccb->cts.xport_specific.spi;
        ccb->cts.protocol = PROTO_SCSI;
        ccb->cts.protocol_version = SCSI_REV_2;
        ccb->cts.transport = XPORT_SPI;
        ccb->cts.transport_version = 2;
        if (ccb->ccb_h.target_lun != CAM_LUN_WILDCARD) {
            scsi->valid = CTS_SCSI_VALID_TQ;
            spi->valid |= CTS_SPI_VALID_DISC;
        } else {
            scsi->valid = 0;
        }
        ccb->ccb_h.status = CAM_REQ_CMP;
        xpt_done(ccb);
        return;
    }
    case XPT_SET_TRAN_SETTINGS:
        ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
        xpt_done(ccb);
        return;
    case XPT_RESET_BUS:
        if (!(sc->flags & AAC_FLAGS_CAM_NORESET)) {
            ccb->ccb_h.status = aac_cam_reset_bus(sim, ccb);
        } else {
            ccb->ccb_h.status = CAM_REQ_CMP;
        }
        xpt_done(ccb);
        return;
    case XPT_ABORT:
        ccb->ccb_h.status = aac_cam_abort_ccb(sim, ccb);
        xpt_done(ccb);
        return;
    case XPT_TERM_IO:
        ccb->ccb_h.status = aac_cam_term_io(sim, ccb);
        xpt_done(ccb);
        return;
    default:
        device_printf(sc->aac_dev, "Unsupported command 0x%x\n",
                      ccb->ccb_h.func_code);
        ccb->ccb_h.status = CAM_PROVIDE_FAIL;
        xpt_done(ccb);
        return;
    }

    /* Async ops that require communcation with the controller */

    if (aac_alloc_command(sc, &cm)) {
        struct aac_event *event;

        xpt_freeze_simq(sim, 1);
        ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
        ccb->ccb_h.sim_priv.entries[0].ptr = camsc;
        event = malloc(sizeof(struct aac_event), M_AACCAM,
                       M_NOWAIT | M_ZERO);
        if (event == NULL) {
            device_printf(sc->aac_dev,
                          "Warning, out of memory for event\n");
            return;
        }
        event->ev_callback = aac_cam_event;
        event->ev_arg = ccb;
        event->ev_type = AAC_EVENT_CMFREE;
        aac_add_event(sc, event);
        return;
    }

    fib = cm->cm_fib;
    srb = (struct aac_srb32 *)&fib->data[0];
    cm->cm_datalen = 0;

    switch (ccb->ccb_h.flags & CAM_DIR_MASK) {
    case CAM_DIR_IN:
        srb->flags = AAC_SRB_FLAGS_DATA_IN;
        cm->cm_flags |= AAC_CMD_DATAIN;
        break;
    case CAM_DIR_OUT:
        srb->flags = AAC_SRB_FLAGS_DATA_OUT;
        cm->cm_flags |= AAC_CMD_DATAOUT;
        break;
    case CAM_DIR_NONE:
        srb->flags = AAC_SRB_FLAGS_NO_DATA_XFER;
        break;
    default:
        srb->flags = AAC_SRB_FLAGS_UNSPECIFIED_DIRECTION;
        cm->cm_flags |= AAC_CMD_DATAIN | AAC_CMD_DATAOUT;
        break;
    }

    switch(ccb->ccb_h.func_code) {
    case XPT_SCSI_IO:
    {
        struct ccb_scsiio *csio = &ccb->csio;

        srb->function = AAC_SRB_FUNC_EXECUTE_SCSI;

        /*
         * Copy the CDB into the SRB.  It's only 6-16 bytes,
         * so a copy is not too expensive.
         */
        srb->cdb_len = csio->cdb_len;
        if (ccb->ccb_h.flags & CAM_CDB_POINTER)
            bcopy(csio->cdb_io.cdb_ptr, (u_int8_t *)&srb->cdb[0],
                  srb->cdb_len);
        else
            bcopy(csio->cdb_io.cdb_bytes, (u_int8_t *)&srb->cdb[0],
                  srb->cdb_len);

        /* Set command */
        fib->Header.Command = (sc->flags & AAC_FLAGS_SG_64BIT) ?
                              ScsiPortCommandU64 : ScsiPortCommand;

        /* Map the s/g list. XXX 32bit addresses only! */
        if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
            if ((ccb->ccb_h.flags & CAM_SCATTER_VALID) == 0) {
                srb->data_len = csio->dxfer_len;
                if (ccb->ccb_h.flags & CAM_DATA_PHYS) {
                    /* Send a 32bit command */
                    fib->Header.Command = ScsiPortCommand;
                    srb->sg_map32.SgCount = 1;
                    srb->sg_map32.SgEntry[0].SgAddress =
                        (uint32_t)(uintptr_t)csio->data_ptr;
                    srb->sg_map32.SgEntry[0].SgByteCount =
                        csio->dxfer_len;
                } else {
                    /*
                     * Arrange things so that the S/G
                     * map will get set up automagically
                     */
                    cm->cm_data = (void *)csio->data_ptr;
                    cm->cm_datalen = csio->dxfer_len;
                    cm->cm_sgtable = &srb->sg_map32;
                }
            } else {
                /* XXX Need to handle multiple s/g elements */
                panic("aac_cam: multiple s/g elements");
            }
        } else {
            srb->sg_map32.SgCount = 0;
            srb->sg_map32.SgEntry[0].SgByteCount = 0;
            srb->data_len = 0;
        }

        break;
    }
    case XPT_RESET_DEV:
        if (!(sc->flags & AAC_FLAGS_CAM_NORESET)) {
            srb->function = AAC_SRB_FUNC_RESET_DEVICE;
            break;
        } else {
            ccb->ccb_h.status = CAM_REQ_CMP;
            xpt_done(ccb);
            return;
        }
    default:
        break;
    }

    srb->bus = camsc->inf->BusNumber; /* Bus number relative to the card */
    srb->target = ccb->ccb_h.target_id;
    srb->lun = ccb->ccb_h.target_lun;
    srb->timeout = ccb->ccb_h.timeout;	/* XXX */
    srb->retry_limit = 0;

    cm->cm_complete = aac_cam_complete;
    cm->cm_private = ccb;
    cm->cm_timestamp = time_uptime;
    cm->cm_queue = AAC_ADAP_NORM_CMD_QUEUE;

    fib->Header.XferState =
        AAC_FIBSTATE_HOSTOWNED	|
        AAC_FIBSTATE_INITIALISED	|
        AAC_FIBSTATE_FROMHOST	|
        AAC_FIBSTATE_REXPECTED	|
        AAC_FIBSTATE_NORM;
    fib->Header.Size = sizeof(struct aac_fib_header) +
                       sizeof(struct aac_srb32);

    aac_enqueue_ready(cm);
    aac_startio(cm->cm_sc);

    return;
}
Esempio n. 18
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;
	}
}
Esempio n. 19
0
/***********************************************************************
 * Handle a request for action from CAM
 */
static void
amr_cam_action(struct cam_sim *sim, union ccb *ccb)
{
	struct amr_softc	*sc = cam_sim_softc(sim);

	switch(ccb->ccb_h.func_code) {

	/*
	 * Perform SCSI I/O to a physical device.
	 */
	case XPT_SCSI_IO:
	{
		struct ccb_hdr		*ccbh = &ccb->ccb_h;
		struct ccb_scsiio	*csio = &ccb->csio;

		/* Validate the CCB */
		ccbh->status = CAM_REQ_INPROG;

		/* check the CDB length */
		if (csio->cdb_len > AMR_MAX_EXTCDB_LEN)
			ccbh->status = CAM_REQ_INVALID;

		if ((csio->cdb_len > AMR_MAX_CDB_LEN) &&
		    (sc->support_ext_cdb == 0))
			ccbh->status = CAM_REQ_INVALID;
	
		/* check that the CDB pointer is not to a physical address */
		if ((ccbh->flags & CAM_CDB_POINTER) &&
		    (ccbh->flags & CAM_CDB_PHYS))
			ccbh->status = CAM_REQ_INVALID;
		/*
		 * if there is data transfer, it must be to/from a virtual
		 * address
		 */
		if ((ccbh->flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
			if (ccbh->flags & CAM_DATA_PHYS)
				/* we can't map it */
				ccbh->status = CAM_REQ_INVALID;
			if (ccbh->flags & CAM_SCATTER_VALID)
				/* we want to do the s/g setup */
				ccbh->status = CAM_REQ_INVALID;
		}
	
		/*
		 * If the command is to a LUN other than 0, fail it.
		 * This is probably incorrect, but during testing the
		 * firmware did not seem to respect the LUN field, and thus
		 * devices appear echoed.
		 */
		if (csio->ccb_h.target_lun != 0)
			ccbh->status = CAM_DEV_NOT_THERE;

		/* if we're happy with the request, queue it for attention */
		if (ccbh->status == CAM_REQ_INPROG) {

			/* save the channel number in the ccb */
			csio->ccb_h.sim_priv.entries[0].field= cam_sim_bus(sim);

			amr_enqueue_ccb(sc, ccb);
			amr_startio(sc);
			return;
		}
		break;
	}

	case XPT_CALC_GEOMETRY:
	{
		cam_calc_geometry(&ccb->ccg, /*extended*/1);
		break;
	}

	/*
	 * Return path stats.  Some of these should probably be amended.
	 */
	case XPT_PATH_INQ:
	{
		struct ccb_pathinq	  *cpi = & ccb->cpi;

		debug(3, "XPT_PATH_INQ");
		cpi->version_num = 1;		   /* XXX??? */
		cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE|PI_WIDE_16;
		cpi->target_sprt = 0;
		cpi->hba_misc = PIM_NOBUSRESET|PIM_SEQSCAN;
		cpi->hba_eng_cnt = 0;
		cpi->max_target = AMR_MAX_TARGETS;
		cpi->max_lun = 0 /* AMR_MAX_LUNS*/;
		cpi->initiator_id = 7;		  /* XXX variable? */
		strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
		strncpy(cpi->hba_vid, "LSI", HBA_IDLEN);
		strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
		cpi->unit_number = cam_sim_unit(sim);
		cpi->bus_id = cam_sim_bus(sim);
		cpi->base_transfer_speed = 132 * 1024;  /* XXX */
		cpi->transport = XPORT_SPI;
		cpi->transport_version = 2;
		cpi->protocol = PROTO_SCSI;
		cpi->protocol_version = SCSI_REV_2;
		cpi->ccb_h.status = CAM_REQ_CMP;

		break;
	}

	case XPT_RESET_BUS:
	{
		struct ccb_pathinq	*cpi = & ccb->cpi;

		debug(1, "XPT_RESET_BUS");
		cpi->ccb_h.status = CAM_REQ_CMP;
		break;
	}

	case XPT_RESET_DEV:
	{
		debug(1, "XPT_RESET_DEV");
		ccb->ccb_h.status = CAM_REQ_CMP;
		break;
	}

	case XPT_GET_TRAN_SETTINGS:
	{
		struct ccb_trans_settings	*cts = &(ccb->cts);

		debug(3, "XPT_GET_TRAN_SETTINGS");

		struct ccb_trans_settings_scsi *scsi;
		struct ccb_trans_settings_spi *spi;

		scsi = &cts->proto_specific.scsi;
		spi = &cts->xport_specific.spi;

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

		if (cts->type == CTS_TYPE_USER_SETTINGS) {
			ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
			break;
		}

		spi->flags = CTS_SPI_FLAGS_DISC_ENB;
		spi->bus_width = MSG_EXT_WDTR_BUS_32_BIT;
		spi->sync_period = 6;   /* 40MHz how wide is this bus? */
		spi->sync_offset = 31;  /* How to extract this from board? */

		spi->valid = CTS_SPI_VALID_SYNC_RATE
			| CTS_SPI_VALID_SYNC_OFFSET
			| CTS_SPI_VALID_BUS_WIDTH
			| CTS_SPI_VALID_DISC;
		scsi->valid = CTS_SCSI_VALID_TQ;
		ccb->ccb_h.status = CAM_REQ_CMP;
		break;
	}

	case XPT_SET_TRAN_SETTINGS:
		debug(3, "XPT_SET_TRAN_SETTINGS");
		ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
		break;


	/*
	 * Reject anything else as unsupported.
	 */
	default:
		/* we can't do this */
		ccb->ccb_h.status = CAM_REQ_INVALID;
		break;
	}

	mtx_assert(&sc->amr_list_lock, MA_OWNED);
	xpt_done(ccb);
}
Esempio n. 20
0
static void hpt_action(struct cam_sim *sim, union ccb *ccb)
{
	PVBUS_EXT vbus_ext = (PVBUS_EXT)cam_sim_softc(sim);

	KdPrint(("hpt_action(fn=%d, id=%d)", ccb->ccb_h.func_code, ccb->ccb_h.target_id));

	hpt_assert_vbus_locked(vbus_ext);
	switch (ccb->ccb_h.func_code) {
	
	case XPT_SCSI_IO:
		hpt_scsi_io(vbus_ext, ccb);
		return;

	case XPT_RESET_BUS:
		ldm_reset_vbus((PVBUS)vbus_ext->vbus);
		break;

	case XPT_GET_TRAN_SETTINGS:
	case XPT_SET_TRAN_SETTINGS:
		ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
		break;

	case XPT_CALC_GEOMETRY:
		cam_calc_geometry(&ccb->ccg, 1);
		break;

	case XPT_PATH_INQ:
	{
		struct ccb_pathinq *cpi = &ccb->cpi;

		cpi->version_num = 1;
		cpi->hba_inquiry = PI_SDTR_ABLE;
		cpi->target_sprt = 0;
		cpi->hba_misc = PIM_NOBUSRESET;
		cpi->hba_eng_cnt = 0;
		cpi->max_target = osm_max_targets;
		cpi->max_lun = 0;
		cpi->unit_number = cam_sim_unit(sim);
		cpi->bus_id = cam_sim_bus(sim);
		cpi->initiator_id = osm_max_targets;
		cpi->base_transfer_speed = 3300;

		strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
		strncpy(cpi->hba_vid, "HPT   ", HBA_IDLEN);
		strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
		cpi->transport = XPORT_SPI;
		cpi->transport_version = 2;
		cpi->protocol = PROTO_SCSI;
		cpi->protocol_version = SCSI_REV_2;
		cpi->ccb_h.status = CAM_REQ_CMP;
		break;
	}

	default:
		ccb->ccb_h.status = CAM_REQ_INVALID;
		break;
	}

	xpt_done(ccb);
	return;
}
Esempio n. 21
0
/***********************************************************************
 * Check for interrupt status
 */
static void
amr_cam_poll(struct cam_sim *sim)
{

	amr_done(cam_sim_softc(sim));
}
Esempio n. 22
0
static void
ahapoll(struct cam_sim *sim)
{
	aha_intr_locked(cam_sim_softc(sim));
}
Esempio n. 23
0
static void
mfip_cam_action(struct cam_sim *sim, union ccb *ccb)
{
	struct mfip_softc *sc = cam_sim_softc(sim);
	struct mfi_softc *mfisc = sc->mfi_sc;

	mtx_assert(&mfisc->mfi_io_lock, MA_OWNED);

	switch (ccb->ccb_h.func_code) {
	case XPT_PATH_INQ:
	{
		struct ccb_pathinq *cpi = &ccb->cpi;

		cpi->version_num = 1;
		cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE|PI_WIDE_16;
		cpi->target_sprt = 0;
		cpi->hba_misc = PIM_NOBUSRESET|PIM_SEQSCAN;
		cpi->hba_eng_cnt = 0;
		cpi->max_target = MFI_SCSI_MAX_TARGETS;
		cpi->max_lun = MFI_SCSI_MAX_LUNS;
		cpi->initiator_id = MFI_SCSI_INITIATOR_ID;
		strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
		strncpy(cpi->hba_vid, "LSI", HBA_IDLEN);
		strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
		cpi->unit_number = cam_sim_unit(sim);
		cpi->bus_id = cam_sim_bus(sim);
		cpi->base_transfer_speed = 150000;
		cpi->transport = XPORT_SAS;
		cpi->transport_version = 0;
		cpi->protocol = PROTO_SCSI;
		cpi->protocol_version = SCSI_REV_2;
		cpi->ccb_h.status = CAM_REQ_CMP;
		break;
	}
	case XPT_RESET_BUS:
		ccb->ccb_h.status = CAM_REQ_CMP;
		break;
	case XPT_RESET_DEV:
		ccb->ccb_h.status = CAM_REQ_CMP;
		break;
	case XPT_GET_TRAN_SETTINGS:
	{
		struct ccb_trans_settings_sas *sas =
		    &ccb->cts.xport_specific.sas;

		ccb->cts.protocol = PROTO_SCSI;
		ccb->cts.protocol_version = SCSI_REV_2;
		ccb->cts.transport = XPORT_SAS;
		ccb->cts.transport_version = 0;

		sas->valid &= ~CTS_SAS_VALID_SPEED;
		sas->bitrate = 150000;

		ccb->ccb_h.status = CAM_REQ_CMP;
		break;
	}
	case XPT_SET_TRAN_SETTINGS:
		ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
		break;
	case XPT_SCSI_IO:
	{
		struct ccb_hdr		*ccbh = &ccb->ccb_h;
		struct ccb_scsiio	*csio = &ccb->csio;

		ccbh->status = CAM_REQ_INPROG;
		if (csio->cdb_len > MFI_SCSI_MAX_CDB_LEN) {
			ccbh->status = CAM_REQ_INVALID;
			break;
		}
		if ((ccbh->flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
			if (ccbh->flags & CAM_DATA_PHYS) {
				ccbh->status = CAM_REQ_INVALID;
				break;
			}
			if (ccbh->flags & CAM_SCATTER_VALID) {
				ccbh->status = CAM_REQ_INVALID;
				break;
			}
		}

		ccbh->ccb_mfip_ptr = sc;
		TAILQ_INSERT_TAIL(&mfisc->mfi_cam_ccbq, ccbh, sim_links.tqe);
		mfi_startio(mfisc);
		return;
	}
	default:
		ccb->ccb_h.status = CAM_REQ_INVALID;
		break;
	}

	xpt_done(ccb);
	return;
}
Esempio n. 24
0
void
cfcs_action(struct cam_sim *sim, union ccb *ccb)
{
	struct cfcs_softc *softc;
	int err;

	softc = (struct cfcs_softc *)cam_sim_softc(sim);
	mtx_assert(&softc->lock, MA_OWNED);

	switch (ccb->ccb_h.func_code) {
	case XPT_SCSI_IO: {
		union ctl_io *io;
		struct ccb_scsiio *csio;

		csio = &ccb->csio;

		/*
		 * Catch CCB flags, like physical address flags, that
	 	 * indicate situations we currently can't handle.
		 */
		if (ccb->ccb_h.flags & CFCS_BAD_CCB_FLAGS) {
			ccb->ccb_h.status = CAM_REQ_INVALID;
			printf("%s: bad CCB flags %#x (all flags %#x)\n",
			       __func__, ccb->ccb_h.flags & CFCS_BAD_CCB_FLAGS,
			       ccb->ccb_h.flags);
			xpt_done(ccb);
			return;
		}

		/*
		 * If we aren't online, there are no devices to see.
		 */
		if (softc->online == 0) {
			ccb->ccb_h.status = CAM_DEV_NOT_THERE;
			xpt_done(ccb);
			return;
		}

		io = ctl_alloc_io(softc->fe.ctl_pool_ref);
		if (io == NULL) {
			printf("%s: can't allocate ctl_io\n", __func__);
			ccb->ccb_h.status = CAM_BUSY | CAM_DEV_QFRZN;
			xpt_freeze_devq(ccb->ccb_h.path, 1);
			xpt_done(ccb);
			return;
		}
		ctl_zero_io(io);
		/* Save pointers on both sides */
		io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr = ccb;
		ccb->ccb_h.io_ptr = io;

		/*
		 * Only SCSI I/O comes down this path, resets, etc. come
		 * down via the XPT_RESET_BUS/LUN CCBs below.
		 */
		io->io_hdr.io_type = CTL_IO_SCSI;
		io->io_hdr.nexus.initid.id = 1;
		io->io_hdr.nexus.targ_port = softc->fe.targ_port;
		/*
		 * XXX KDM how do we handle target IDs?
		 */
		io->io_hdr.nexus.targ_target.id = ccb->ccb_h.target_id;
		io->io_hdr.nexus.targ_lun = ccb->ccb_h.target_lun;
		/*
		 * This tag scheme isn't the best, since we could in theory
		 * have a very long-lived I/O and tag collision, especially
		 * in a high I/O environment.  But it should work well
		 * enough for now.  Since we're using unsigned ints,
		 * they'll just wrap around.
		 */
		io->scsiio.tag_num = softc->cur_tag_num++;
		csio->tag_id = io->scsiio.tag_num;
		switch (csio->tag_action) {
		case CAM_TAG_ACTION_NONE:
			io->scsiio.tag_type = CTL_TAG_UNTAGGED;
			break;
		case MSG_SIMPLE_TASK:
			io->scsiio.tag_type = CTL_TAG_SIMPLE;
			break;
		case MSG_HEAD_OF_QUEUE_TASK:
        		io->scsiio.tag_type = CTL_TAG_HEAD_OF_QUEUE;
			break;
		case MSG_ORDERED_TASK:
        		io->scsiio.tag_type = CTL_TAG_ORDERED;
			break;
		case MSG_ACA_TASK:
			io->scsiio.tag_type = CTL_TAG_ACA;
			break;
		default:
			io->scsiio.tag_type = CTL_TAG_UNTAGGED;
			printf("%s: unhandled tag type %#x!!\n", __func__,
			       csio->tag_action);
			break;
		}
		if (csio->cdb_len > sizeof(io->scsiio.cdb)) {
			printf("%s: WARNING: CDB len %d > ctl_io space %zd\n",
			       __func__, csio->cdb_len, sizeof(io->scsiio.cdb));
		}
		io->scsiio.cdb_len = min(csio->cdb_len, sizeof(io->scsiio.cdb));
		bcopy(csio->cdb_io.cdb_bytes, io->scsiio.cdb,
		      io->scsiio.cdb_len);

		err = ctl_queue(io);
		if (err != CTL_RETVAL_COMPLETE) {
			printf("%s: func %d: error %d returned by "
			       "ctl_queue()!\n", __func__,
			       ccb->ccb_h.func_code, err);
			ctl_free_io(io);
		} else {
			ccb->ccb_h.status |= CAM_SIM_QUEUED;
		}
		break;
	}
	case XPT_ABORT: {
		union ctl_io *io;
		union ccb *abort_ccb;

		abort_ccb = ccb->cab.abort_ccb;

		if (abort_ccb->ccb_h.func_code != XPT_SCSI_IO) {
			ccb->ccb_h.status = CAM_REQ_INVALID;
			xpt_done(ccb);
		}

		/*
		 * If we aren't online, there are no devices to talk to.
		 */
		if (softc->online == 0) {
			ccb->ccb_h.status = CAM_DEV_NOT_THERE;
			xpt_done(ccb);
			return;
		}

		io = ctl_alloc_io(softc->fe.ctl_pool_ref);
		if (io == NULL) {
			ccb->ccb_h.status = CAM_BUSY | CAM_DEV_QFRZN;
			xpt_freeze_devq(ccb->ccb_h.path, 1);
			xpt_done(ccb);
			return;
		}

		ctl_zero_io(io);
		/* Save pointers on both sides */
		io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr = ccb;
		ccb->ccb_h.io_ptr = io;

		io->io_hdr.io_type = CTL_IO_TASK;
		io->io_hdr.nexus.initid.id = 1;
		io->io_hdr.nexus.targ_port = softc->fe.targ_port;
		io->io_hdr.nexus.targ_target.id = ccb->ccb_h.target_id;
		io->io_hdr.nexus.targ_lun = ccb->ccb_h.target_lun;
		io->taskio.task_action = CTL_TASK_ABORT_TASK;
		io->taskio.tag_num = abort_ccb->csio.tag_id;
		switch (abort_ccb->csio.tag_action) {
		case CAM_TAG_ACTION_NONE:
			io->taskio.tag_type = CTL_TAG_UNTAGGED;
			break;
		case MSG_SIMPLE_TASK:
			io->taskio.tag_type = CTL_TAG_SIMPLE;
			break;
		case MSG_HEAD_OF_QUEUE_TASK:
        		io->taskio.tag_type = CTL_TAG_HEAD_OF_QUEUE;
			break;
		case MSG_ORDERED_TASK:
        		io->taskio.tag_type = CTL_TAG_ORDERED;
			break;
		case MSG_ACA_TASK:
			io->taskio.tag_type = CTL_TAG_ACA;
			break;
		default:
			io->taskio.tag_type = CTL_TAG_UNTAGGED;
			printf("%s: unhandled tag type %#x!!\n", __func__,
			       abort_ccb->csio.tag_action);
			break;
		}
		err = ctl_queue(io);
		if (err != CTL_RETVAL_COMPLETE) {
			printf("%s func %d: error %d returned by "
			       "ctl_queue()!\n", __func__,
			       ccb->ccb_h.func_code, err);
			ctl_free_io(io);
		}
		break;
	}
	case XPT_GET_TRAN_SETTINGS: {
		struct ccb_trans_settings *cts;
		struct ccb_trans_settings_scsi *scsi;
		struct ccb_trans_settings_fc *fc;

		cts = &ccb->cts;
		scsi = &cts->proto_specific.scsi;
		fc = &cts->xport_specific.fc;

		
		cts->protocol = PROTO_SCSI;
		cts->protocol_version = SCSI_REV_SPC2;
		cts->transport = XPORT_FC;
		cts->transport_version = 0;

		scsi->valid = CTS_SCSI_VALID_TQ;
		scsi->flags = CTS_SCSI_FLAGS_TAG_ENB;
		fc->valid = CTS_FC_VALID_SPEED;
		fc->bitrate = 800000;
		fc->wwnn = softc->wwnn;
		fc->wwpn = softc->wwpn;
       		fc->port = softc->fe.targ_port;
		fc->valid |= CTS_FC_VALID_WWNN | CTS_FC_VALID_WWPN |
			CTS_FC_VALID_PORT; 
		ccb->ccb_h.status = CAM_REQ_CMP;
		break;
	}
	case XPT_SET_TRAN_SETTINGS:
		/* XXX KDM should we actually do something here? */
		ccb->ccb_h.status = CAM_REQ_CMP;
		break;
	case XPT_RESET_BUS:
	case XPT_RESET_DEV: {
		union ctl_io *io;

		/*
		 * If we aren't online, there are no devices to talk to.
		 */
		if (softc->online == 0) {
			ccb->ccb_h.status = CAM_DEV_NOT_THERE;
			xpt_done(ccb);
			return;
		}

		io = ctl_alloc_io(softc->fe.ctl_pool_ref);
		if (io == NULL) {
			ccb->ccb_h.status = CAM_BUSY | CAM_DEV_QFRZN;
			xpt_freeze_devq(ccb->ccb_h.path, 1);
			xpt_done(ccb);
			return;
		}

		ctl_zero_io(io);
		/* Save pointers on both sides */
		io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr = ccb;
		ccb->ccb_h.io_ptr = io;

		io->io_hdr.io_type = CTL_IO_TASK;
		io->io_hdr.nexus.initid.id = 0;
		io->io_hdr.nexus.targ_port = softc->fe.targ_port;
		io->io_hdr.nexus.targ_target.id = ccb->ccb_h.target_id;
		io->io_hdr.nexus.targ_lun = ccb->ccb_h.target_lun;
		if (ccb->ccb_h.func_code == XPT_RESET_BUS)
			io->taskio.task_action = CTL_TASK_BUS_RESET;
		else
			io->taskio.task_action = CTL_TASK_LUN_RESET;

		err = ctl_queue(io);
		if (err != CTL_RETVAL_COMPLETE) {
			printf("%s func %d: error %d returned by "
			      "ctl_queue()!\n", __func__,
			      ccb->ccb_h.func_code, err);
			ctl_free_io(io);
		}
		break;
	}
	case XPT_CALC_GEOMETRY:
		cam_calc_geometry(&ccb->ccg, 1);
		xpt_done(ccb);
		break;
	case XPT_PATH_INQ: {
		struct ccb_pathinq *cpi;

		cpi = &ccb->cpi;

		cpi->version_num = 0;
		cpi->hba_inquiry = PI_TAG_ABLE;
		cpi->target_sprt = 0;
		cpi->hba_misc = 0;
		cpi->hba_eng_cnt = 0;
		cpi->max_target = 1;
		cpi->max_lun = 1024;
		/* Do we really have a limit? */
		cpi->maxio = 1024 * 1024;
		cpi->async_flags = 0;
		cpi->hpath_id = 0;
		cpi->initiator_id = 0;

		strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
		strncpy(cpi->hba_vid, "FreeBSD", HBA_IDLEN);
		strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
		cpi->unit_number = 0;
		cpi->bus_id = 0;
		cpi->base_transfer_speed = 800000;
		cpi->protocol = PROTO_SCSI;
		cpi->protocol_version = SCSI_REV_SPC2;
		/*
		 * Pretend to be Fibre Channel.
		 */
		cpi->transport = XPORT_FC;
		cpi->transport_version = 0;
		cpi->xport_specific.fc.wwnn = softc->wwnn;
		cpi->xport_specific.fc.wwpn = softc->wwpn;
		cpi->xport_specific.fc.port = softc->fe.targ_port;
		cpi->xport_specific.fc.bitrate = 8 * 1000 * 1000;
		cpi->ccb_h.status = CAM_REQ_CMP;
		break;
	}
	default:
		ccb->ccb_h.status = CAM_PROVIDE_FAIL;
		printf("%s: unsupported CCB type %#x\n", __func__,
		       ccb->ccb_h.func_code);
		xpt_done(ccb);
		break;
	}
}
Esempio n. 25
0
/*
 * Function to poll for command completion when
 * interrupts are disabled (crash dumps)
 */
static void
adv_poll(struct cam_sim *sim)
{

	adv_intr_locked(cam_sim_softc(sim));
}
/**
 * mrsas_poll:               Polling entry point 
 * input:                    Pointer to SIM  
 *
 * This is currently a stub function.
 */
static void mrsas_poll(struct cam_sim *sim)
{
    struct mrsas_softc *sc = (struct mrsas_softc *)cam_sim_softc(sim);
    mrsas_isr((void *) sc);
}
Esempio n. 27
0
static void
adv_action(struct cam_sim *sim, union ccb *ccb)
{
	struct adv_softc *adv;

	CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("adv_action\n"));

	adv = (struct adv_softc *)cam_sim_softc(sim);
	mtx_assert(&adv->lock, MA_OWNED);

	switch (ccb->ccb_h.func_code) {
	/* Common cases first */
	case XPT_SCSI_IO:	/* Execute the requested I/O operation */
	{
		struct	ccb_hdr *ccb_h;
		struct	ccb_scsiio *csio;
		struct	adv_ccb_info *cinfo;
		int error;

		ccb_h = &ccb->ccb_h;
		csio = &ccb->csio;
		cinfo = adv_get_ccb_info(adv);
		if (cinfo == NULL)
			panic("XXX Handle CCB info error!!!");

		ccb_h->ccb_cinfo_ptr = cinfo;
		cinfo->ccb = ccb;

		error = bus_dmamap_load_ccb(adv->buffer_dmat,
					    cinfo->dmamap,
					    ccb,
					    adv_execute_ccb,
					    csio, /*flags*/0);
		if (error == EINPROGRESS) {
			/*
			 * So as to maintain ordering, freeze the controller
			 * queue until our mapping is returned.
			 */
			adv_set_state(adv, ADV_BUSDMA_BLOCK);
		}
		break;
	}
	case XPT_RESET_DEV:	/* Bus Device Reset the specified SCSI device */
	case XPT_TARGET_IO:	/* Execute target I/O request */
	case XPT_ACCEPT_TARGET_IO:	/* Accept Host Target Mode CDB */
	case XPT_CONT_TARGET_IO:	/* Continue Host Target I/O Connection*/
	case XPT_EN_LUN:		/* Enable LUN as a target */
	case XPT_ABORT:			/* Abort the specified CCB */
		/* XXX Implement */
		ccb->ccb_h.status = CAM_REQ_INVALID;
		xpt_done(ccb);
		break;
#define	IS_CURRENT_SETTINGS(c)	(c->type == CTS_TYPE_CURRENT_SETTINGS)
#define	IS_USER_SETTINGS(c)	(c->type == CTS_TYPE_USER_SETTINGS)
	case XPT_SET_TRAN_SETTINGS:
	{
		struct ccb_trans_settings_scsi *scsi;
		struct ccb_trans_settings_spi *spi;
		struct	 ccb_trans_settings *cts;
		target_bit_vector targ_mask;
		struct adv_transinfo *tconf;
		u_int	 update_type;

		cts = &ccb->cts;
		targ_mask = ADV_TID_TO_TARGET_MASK(cts->ccb_h.target_id);
		update_type = 0;

		/*
		 * The user must specify which type of settings he wishes
		 * to change.
		 */
		if (IS_CURRENT_SETTINGS(cts) && !IS_USER_SETTINGS(cts)) {
			tconf = &adv->tinfo[cts->ccb_h.target_id].current;
			update_type |= ADV_TRANS_GOAL;
		} else if (IS_USER_SETTINGS(cts) && !IS_CURRENT_SETTINGS(cts)) {
			tconf = &adv->tinfo[cts->ccb_h.target_id].user;
			update_type |= ADV_TRANS_USER;
		} else {
			ccb->ccb_h.status = CAM_REQ_INVALID;
			break;
		}
		
		scsi = &cts->proto_specific.scsi;
		spi = &cts->xport_specific.spi;
		if ((update_type & ADV_TRANS_GOAL) != 0) {
			if ((spi->valid & CTS_SPI_VALID_DISC) != 0) {
				if ((spi->flags & CTS_SPI_FLAGS_DISC_ENB) != 0)
					adv->disc_enable |= targ_mask;
				else
					adv->disc_enable &= ~targ_mask;
				adv_write_lram_8(adv, ADVV_DISC_ENABLE_B,
						 adv->disc_enable); 
			}

			if ((scsi->valid & CTS_SCSI_VALID_TQ) != 0) {
				if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0)
					adv->cmd_qng_enabled |= targ_mask;
				else
					adv->cmd_qng_enabled &= ~targ_mask;
			}
		}

		if ((update_type & ADV_TRANS_USER) != 0) {
			if ((spi->valid & CTS_SPI_VALID_DISC) != 0) {
				if ((spi->flags & CTS_SPI_VALID_DISC) != 0)
					adv->user_disc_enable |= targ_mask;
				else
					adv->user_disc_enable &= ~targ_mask;
			}

			if ((scsi->valid & CTS_SCSI_VALID_TQ) != 0) {
				if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0)
					adv->user_cmd_qng_enabled |= targ_mask;
				else
					adv->user_cmd_qng_enabled &= ~targ_mask;
			}
		}
		
		/*
		 * If the user specifies either the sync rate, or offset,
		 * but not both, the unspecified parameter defaults to its
		 * current value in transfer negotiations.
		 */
		if (((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0)
		 || ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)) {
			/*
			 * If the user provided a sync rate but no offset,
			 * use the current offset.
			 */
			if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) == 0)
				spi->sync_offset = tconf->offset;

			/*
			 * If the user provided an offset but no sync rate,
			 * use the current sync rate.
			 */
			if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) == 0)
				spi->sync_period = tconf->period;

			adv_period_offset_to_sdtr(adv, &spi->sync_period,
						  &spi->sync_offset,
						  cts->ccb_h.target_id);
			
			adv_set_syncrate(adv, /*struct cam_path */NULL,
					 cts->ccb_h.target_id, spi->sync_period,
					 spi->sync_offset, update_type);
		}

		ccb->ccb_h.status = CAM_REQ_CMP;
		xpt_done(ccb);
		break;
	}
	case XPT_GET_TRAN_SETTINGS:
	/* Get default/user set transfer settings for the target */
	{
		struct ccb_trans_settings_scsi *scsi;
		struct ccb_trans_settings_spi *spi;
		struct ccb_trans_settings *cts;
		struct adv_transinfo *tconf;
		target_bit_vector target_mask;

		cts = &ccb->cts;
		target_mask = ADV_TID_TO_TARGET_MASK(cts->ccb_h.target_id);

		scsi = &cts->proto_specific.scsi;
		spi = &cts->xport_specific.spi;

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

		scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
		spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;

		if (cts->type == CTS_TYPE_CURRENT_SETTINGS) {
			tconf = &adv->tinfo[cts->ccb_h.target_id].current;
			if ((adv->disc_enable & target_mask) != 0)
				spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
			if ((adv->cmd_qng_enabled & target_mask) != 0)
				scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
		} else {
			tconf = &adv->tinfo[cts->ccb_h.target_id].user;
			if ((adv->user_disc_enable & target_mask) != 0)
				spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
			if ((adv->user_cmd_qng_enabled & target_mask) != 0)
				scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
		}
		spi->sync_period = tconf->period;
		spi->sync_offset = tconf->offset;
		spi->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
		spi->valid = CTS_SPI_VALID_SYNC_RATE
			   | CTS_SPI_VALID_SYNC_OFFSET
			   | CTS_SPI_VALID_BUS_WIDTH
			   | CTS_SPI_VALID_DISC;
		scsi->valid = CTS_SCSI_VALID_TQ;
		ccb->ccb_h.status = CAM_REQ_CMP;
		xpt_done(ccb);
		break;
	}
	case XPT_CALC_GEOMETRY:
	{
		int	  extended;

		extended = (adv->control & ADV_CNTL_BIOS_GT_1GB) != 0;
		cam_calc_geometry(&ccb->ccg, extended); 
		xpt_done(ccb);
		break;
	}
	case XPT_RESET_BUS:		/* Reset the specified SCSI bus */
	{

		adv_stop_execution(adv);
		adv_reset_bus(adv, /*initiate_reset*/TRUE);
		adv_start_execution(adv);

		ccb->ccb_h.status = CAM_REQ_CMP;
		xpt_done(ccb);
		break;
	}
	case XPT_TERM_IO:		/* Terminate the I/O process */
		/* XXX Implement */
		ccb->ccb_h.status = CAM_REQ_INVALID;
		xpt_done(ccb);
		break;
	case XPT_PATH_INQ:		/* Path routing inquiry */
	{
		struct ccb_pathinq *cpi = &ccb->cpi;
		
		cpi->version_num = 1; /* XXX??? */
		cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE;
		cpi->target_sprt = 0;
		cpi->hba_misc = 0;
		cpi->hba_eng_cnt = 0;
		cpi->max_target = 7;
		cpi->max_lun = 7;
		cpi->initiator_id = adv->scsi_id;
		cpi->bus_id = cam_sim_bus(sim);
		cpi->base_transfer_speed = 3300;
		strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
		strncpy(cpi->hba_vid, "Advansys", HBA_IDLEN);
		strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
		cpi->unit_number = cam_sim_unit(sim);
		cpi->ccb_h.status = CAM_REQ_CMP;
                cpi->transport = XPORT_SPI;
                cpi->transport_version = 2;
                cpi->protocol = PROTO_SCSI;
                cpi->protocol_version = SCSI_REV_2;
		xpt_done(ccb);
		break;
	}
	default:
		ccb->ccb_h.status = CAM_REQ_INVALID;
		xpt_done(ccb);
		break;
	}
}
Esempio n. 28
0
static void
isp_poll(struct cam_sim *sim)
{
	isp_intr((struct ispsoftc *) cam_sim_softc(sim));
}
Esempio n. 29
0
/********************************************************************************
 * Handle an action requested by CAM
 */
static void
mly_cam_action(struct cam_sim *sim, union ccb *ccb)
{
    struct mly_softc	*sc = cam_sim_softc(sim);

    debug_called(2);

    switch (ccb->ccb_h.func_code) {

	/* perform SCSI I/O */
    case XPT_SCSI_IO:
    {
	struct ccb_scsiio	*csio = &ccb->csio;
	int			bus, target;

	bus = cam_sim_bus(sim);
	target = csio->ccb_h.target_id;

	debug(2, "XPT_SCSI_IO %d:%d:%d", bus, target, ccb->ccb_h.target_lun);

	/*  check for I/O attempt to a protected device */
	if (sc->mly_btl[bus][target].mb_flags & MLY_BTL_PROTECTED) {
	    debug(2, "  device protected");
	    csio->ccb_h.status = CAM_REQ_CMP_ERR;
	}

	/* check for I/O attempt to nonexistent device */
	if (!(sc->mly_btl[bus][target].mb_flags & (MLY_BTL_LOGICAL | MLY_BTL_PHYSICAL))) {
	    debug(2, "  device does not exist");
	    csio->ccb_h.status = CAM_REQ_CMP_ERR;
	}

	/* XXX increase if/when we support large SCSI commands */
	if (csio->cdb_len > MLY_CMD_SCSI_SMALL_CDB) {
	    debug(2, "  command too large (%d > %d)", csio->cdb_len, MLY_CMD_SCSI_SMALL_CDB);
	    csio->ccb_h.status = CAM_REQ_CMP_ERR;
	}

        /* check that the CDB pointer is not to a physical address */
        if ((csio->ccb_h.flags & CAM_CDB_POINTER) && (csio->ccb_h.flags & CAM_CDB_PHYS)) {
	    debug(2, "  CDB pointer is to physical address");
            csio->ccb_h.status = CAM_REQ_CMP_ERR;
	}

        /* if there is data transfer, it must be to/from a virtual address */
        if ((csio->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
            if (csio->ccb_h.flags & CAM_DATA_PHYS) {		/* we can't map it */
		debug(2, "  data pointer is to physical address");
                csio->ccb_h.status = CAM_REQ_CMP_ERR;
	    }
            if (csio->ccb_h.flags & CAM_SCATTER_VALID) {	/* we want to do the s/g setup */
		debug(2, "  data has premature s/g setup");
                csio->ccb_h.status = CAM_REQ_CMP_ERR;
	    }
        }

	/* abandon aborted ccbs or those that have failed validation */
	if ((csio->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_INPROG) {
	    debug(2, "abandoning CCB due to abort/validation failure");
	    break;
	}

	/* save the channel number in the ccb */
	csio->ccb_h.sim_priv.entries[0].field = bus;

	/* enqueue the ccb and start I/O */
	mly_enqueue_ccb(sc, ccb);
	mly_startio(sc);
	return;
    }

	/* perform geometry calculations */
    case XPT_CALC_GEOMETRY:
    {
	struct ccb_calc_geometry	*ccg = &ccb->ccg;
        u_int32_t			secs_per_cylinder;

	debug(2, "XPT_CALC_GEOMETRY %d:%d:%d", cam_sim_bus(sim), ccb->ccb_h.target_id, ccb->ccb_h.target_lun);

	if (sc->mly_controllerparam->bios_geometry == MLY_BIOSGEOM_8G) {
	    ccg->heads = 255;
            ccg->secs_per_track = 63;
	} else {				/* MLY_BIOSGEOM_2G */
	    ccg->heads = 128;
            ccg->secs_per_track = 32;
	}
	secs_per_cylinder = ccg->heads * ccg->secs_per_track;
        ccg->cylinders = ccg->volume_size / secs_per_cylinder;
        ccb->ccb_h.status = CAM_REQ_CMP;
        break;
    }

	/* handle path attribute inquiry */
    case XPT_PATH_INQ:
    {
	struct ccb_pathinq	*cpi = &ccb->cpi;

	debug(2, "XPT_PATH_INQ %d:%d:%d", cam_sim_bus(sim), ccb->ccb_h.target_id, ccb->ccb_h.target_lun);

	cpi->version_num = 1;
	cpi->hba_inquiry = PI_TAG_ABLE;		/* XXX extra flags for physical channels? */
	cpi->target_sprt = 0;
	cpi->hba_misc = 0;
	cpi->max_target = MLY_MAX_TARGETS - 1;
	cpi->max_lun = MLY_MAX_LUNS - 1;
	cpi->initiator_id = sc->mly_controllerparam->initiator_id;
	strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
        strncpy(cpi->hba_vid, "BSDi", HBA_IDLEN);
        strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
        cpi->unit_number = cam_sim_unit(sim);
        cpi->bus_id = cam_sim_bus(sim);
	cpi->base_transfer_speed = 132 * 1024;	/* XXX what to set this to? */
	ccb->ccb_h.status = CAM_REQ_CMP;
	break;
    }

    default:		/* we can't do this */
	debug(2, "unspported func_code = 0x%x", ccb->ccb_h.func_code);
	ccb->ccb_h.status = CAM_REQ_INVALID;
	break;
    }

    xpt_done(ccb);
}