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; } }
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; } } }
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); }
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 {
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 ); }