Exemplo n.º 1
0
static void mmc_msense(SIM_HBA *hba)
{
	SIM_MMC_EXT			*ext;
	CCB_SCSIIO			*ccb;
	MODE_PARM_HEADER10	*hdr;

	ext = (SIM_MMC_EXT *)hba->ext;
	ccb = ext->nexus;

	if (!(ext->eflags & MMC_EFLAG_READY)) {
		mmc_sense(hba, SK_NOT_RDY, ASC_MEDIA_NOT_PRESENT, 0);
		return;
	}

	switch (ccb->cam_cdb_io.cam_cdb_bytes[2]) {
		case MP_RW_ERR:
			hdr = (MODE_PARM_HEADER10 *)ccb->cam_data.cam_data_ptr;
			memset(hdr, 0, sizeof(*hdr));
			if (ext->eflags & MMC_EFLAG_WP)
				hdr->device_specific |= MP_DS_WP;

			ccb->cam_ch.cam_status = CAM_REQ_CMP;
			ccb->cam_scsi_status   = SCS_GOOD;
			break;
		default:
			mmc_sense(hba, SK_ILLEGAL, ASC_INVALID_FIELD, 0);
			break;
	}
}
Exemplo n.º 2
0
static void mmc_error(SIM_HBA *hba, int mmc_status)
{
	SIM_MMC_EXT	*ext = (SIM_MMC_EXT *)hba->ext;
	CCB_SCSIIO	*ccb = ext->nexus;

	if (ccb) {
		switch (mmc_status) {
			case MMC_DATA_OVERRUN:
				ccb->cam_ch.cam_status = CAM_DATA_RUN_ERR;
				break;
			case MMC_NOT_PRESENT:
				mmc_sense(hba, SK_NOT_RDY, ASC_MEDIA_NOT_PRESENT, 0);
				break;
			case MMC_TIMEOUT:
			case MMC_COMMAND_FAILURE:
				mmc_reset(hba);
				ccb->cam_ch.cam_status = CAM_CMD_TIMEOUT;
				break;
			case MMC_READ_ERROR:			// CRC errors
			case MMC_WRITE_ERROR:
			default:
				ccb->cam_ch.cam_status = CAM_CMD_TIMEOUT;
				break;
		}
	}
}
Exemplo n.º 3
0
static void mmc_unit_ready(SIM_HBA *hba)
{
	SIM_MMC_EXT	*ext = (SIM_MMC_EXT *)hba->ext;
	CCB_SCSIIO	*ccb = ext->nexus;

	if (ext->eflags & MMC_EFLAG_MEDIA_CHANGED) {
		mmc_sense(hba, SK_UNIT_ATN, ASC_MEDIUM_CHANGED, ASCQ_UNKNOWN_CHANGED);
		atomic_clr(&ext->eflags, MMC_EFLAG_MEDIA_CHANGED);
	} else if (ext->eflags & MMC_EFLAG_READY) {
		if (ext->detect(hba) != MMC_SUCCESS) {
			mmc_media_check(hba);
			mmc_sense(hba, SK_NOT_RDY, ASC_MEDIA_NOT_PRESENT, 0);
		} else
			ccb->cam_ch.cam_status = CAM_REQ_CMP;
	} else
		mmc_sense(hba, SK_NOT_RDY, ASC_MEDIA_NOT_PRESENT, 0);
}
Exemplo n.º 4
0
static void mmc_inquiry(SIM_HBA *hba)
{
	SIM_MMC_EXT		*ext;
	CCB_SCSIIO		*ccb;
	SCSI_INQUIRY	*iptr;
	char			buf[8];

	ext		= (SIM_MMC_EXT *)hba->ext;
	ccb		= ext->nexus;
	iptr	= (SCSI_INQUIRY *)ccb->cam_data.cam_data_ptr;

	if (ccb->cam_ch.cam_flags & CAM_DATA_PHYS) {
		mmc_error(hba, CAM_PROVIDE_FAIL);
		return;
	}

	if (ext->state == MMCSD_STATE_IDENT)
		return;

	memset(iptr, 0, sizeof(*iptr));

	iptr->peripheral	= D_DIR_ACC | INQ_QUAL_AVAIL;
	iptr->rmb			= CAM_TRUE;		// removable
	iptr->version		= 1;
	iptr->adlen			= 32;

	if (!(ext->eflags & MMC_EFLAG_READY)) {
		mmc_sense(hba, SK_NOT_RDY, ASC_MEDIA_NOT_PRESENT, 0);
		return;
	}

	if (ext->version < MMC_VERSION_1) {
		/* Vendor ID */
		strcpy((char *)&iptr->vend_id[0], "SD:");
		ultoa(ext->cid.sd_cid.mid, buf, 10);
		iptr->vend_id[3] = buf[0];
		iptr->vend_id[4] = buf[1];
		iptr->vend_id[5] = buf[2];

		/* Product ID */
		strcpy((char *)&iptr->prod_id[0], (char *)ext->cid.sd_cid.pnm);

		/* Product revision level, BCD code */
		iptr->prod_rev[0] = (ext->cid.sd_cid.prv >> 4) + '0';
		iptr->prod_rev[1] = '.';
		iptr->prod_rev[2] = (ext->cid.sd_cid.prv & 0x0F) + '0';
	} else {
Exemplo n.º 5
0
int mmc_evpd_inquiry( SIM_HBA *hba, CCB_SCSIIO *ccb )
{
	SIM_MMC_EXT						*ext;
	VPD_HEADER						*vh;
	BLOCK_LIMITS					*bl;
	ID_HEADER		*id;
	BLOCK_DEVICE_CHARACTERISTICS	*bdc;
	uint8_t							*is;
	uint8_t							*vpd;
	uint16_t						lps;

	ext	= (SIM_MMC_EXT *)hba->ext;

	vpd	= (uint8_t *)ccb->cam_data.cam_data_ptr;
	vh	= (VPD_HEADER *)vpd;
	id	= (ID_HEADER *)(vh + 1);
	is	= (uint8_t *)(id + 1);
	bl	= (BLOCK_LIMITS *)(vh+1);
	bdc	= (BLOCK_DEVICE_CHARACTERISTICS *)(vh+1);
	memset( vpd, 0, ccb->cam_dxfer_len );

	switch( ccb->cam_cdb_io.cam_cdb_bytes[2] ) {
		case INQ_PC_VPD_SUPPORTED: {
			uint8_t		evp_sup[] = { D_DIR_ACC, INQ_PC_VPD_SUPPORTED, 0, 3,
							INQ_PC_VPD_SUPPORTED, INQ_PC_BLOCK_LIMITS,
							INQ_PC_BLOCK_DEVICE_CHARACTERISTICS };

			if( ccb->cam_dxfer_len < sizeof( evp_sup ) ) {
				return( mmc_sense( hba, SK_ILLEGAL, ASC_INVALID_FIELD, 0 ) );
			}
			memcpy( vpd, evp_sup, sizeof( evp_sup ) );
			break;
		}

		case INQ_PC_BLOCK_LIMITS:
			if( ccb->cam_dxfer_len < ( sizeof( *vh ) + sizeof( *bl ) ) ) {
				return( mmc_sense( hba, SK_ILLEGAL, ASC_INVALID_FIELD, 0 ) );
			}
			vh->peripheral		= D_DIR_ACC;
			vh->page_code		= INQ_PC_BLOCK_LIMITS;
			vh->page_length		= ENDIAN_BE16( 60 );

			lps = 1;
			bl->optimal_xfer_len_granularity	= ENDIAN_BE16( lps );

			if( ext->eflags & MMC_EFLAG_TRIM ) {
				bl->max_unmap_lba_count			= ENDIAN_BE32( MMC_TRIM_MAX_LBA );
				bl->max_unmap_desc_count		= ENDIAN_BE32( 1 );
				bl->optimal_unmap_granularity	= ENDIAN_BE32( 1 );
			}
			break;

		case INQ_PC_BLOCK_DEVICE_CHARACTERISTICS:
			if( ccb->cam_dxfer_len < ( sizeof( *vh ) + sizeof( *bdc ) ) ) {
				return( mmc_sense( hba, SK_ILLEGAL, ASC_INVALID_FIELD, 0 ) );
			}
			vh->peripheral				= D_DIR_ACC;
			vh->page_code				= INQ_PC_BLOCK_DEVICE_CHARACTERISTICS;
			vh->page_length				= ENDIAN_BE16( 60 );

			bdc->medium_rotation_rate	= ENDIAN_BE16( 1 );		// 1 indicates non rotating
			bdc->nominal_form_factor	= 0;

			break;

		default:
			return( mmc_sense( hba, SK_ILLEGAL, ASC_INVALID_FIELD, 0 ) );
			break;
	}

	ccb->cam_ch.cam_status	= CAM_REQ_CMP;
	ccb->cam_scsi_status	= SCS_GOOD;
	return( ccb->cam_ch.cam_status );
}