📄 usbtargrbccmd.c
字号:
case 3: /* Place device in Standby condition */ break; case 5: /* Place device in Sleep condition */ break; case 7: /* optional control */ default: break; } /* * Save power conditions: * NOTE: The device shall terminate any command received that requires * more power consumption than allowed by the START STOP UNIT command's * most recent power condition setting. Status shall be ERROR, the sense * key to ILLEGAL REQUEST (05h), and the ASC/ASCQ to LOW POWER CONDITION * ACTIVE (5Eh/00h). It is not an error to request a device be placed * into the same power consumption level in which it currently resides. */ g_pwrConditions = pwrConditions; } else { /* * If a removable medium device, in either PREVENT state 01b or 11b, * receives a START STOP UNIT command with the POWER CONDITIONS field * set to the Sleep state (5), this routine will return ERROR with * the sense key set to ILLEGAL REQUEST (05h), and the ASC/ASCQ to * ILLEGAL POWER CONDITION REQUEST (2Ch/05h). */ if (g_pwrConditions == 0x5) { if (g_mediaPrevent == 0x1 || g_mediaPrevent == 0x3) { usbTargRbcSenseDataSet(SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ADSENSE_CMDSEQ_ERROR, SCSI_SENSEQ_ILLEGAL_POWER_CONDITION_REQUEST); return(ERROR); } } /* either load or eject the media */ if (loEj == 1) { if (start == 1) { /* load medium: set media removed flag to loaded */ g_mediaRemoved = FALSE; } else { /* unload medium: set media removed flag to ejected */ g_mediaRemoved = TRUE; } } else /* get media ready for data transfer */ { if (start == 1) /* media ready for data transfers */ g_mediaReady = TRUE; else /* media inaccessible for data transfers */ g_mediaReady = FALSE; } } /* set sense data to no sense */ usbTargRbcSenseDataSet(SCSI_SENSE_NO_SENSE, SCSI_ADSENSE_NO_SENSE, 0); return(OK); }/********************************************************************************* usbTargRbcPreventAllowRemoval - prevent or allow the removal of the RBC device** This routine prevents or allows the removal of the RBC block I/O device.** RETURNS: OK or ERROR* * ERRNO:* none*/STATUS usbTargRbcPreventAllowRemoval ( UINT8 arg[6] /* the RBC command */ ) { UINT8 prevent = arg[4] & 0x3; /* prevent media removal flag */ switch (prevent) { case 0: /* * Medium removal shall be allowed from both the data transport * element and the attached medium changer (if any) */ break; case 1: /* * Medium removal shall be prohibited from the data transport * element but allowed from the attached medium changer (if any) */ break; case 2: /* * Medium removal shall be allowed for the data transport element * but prohibited for the attached medium changer. */ break; case 3: /* * Medium removal shall be prohibited for both the data transport * element and the attached medium changer. */ break; default: /* * set the sense key to ILLEGAL REQUEST (0x5) and set the ASC to * INVALID COMMAND OPERATION CODE (0x20) */ usbTargRbcSenseDataSet (SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ADSENSE_ILLEGAL_COMMAND, 0); return(ERROR); } /* save prevent/allow flag for use in usbTargRbcStartStop() cmd */ g_mediaPrevent = prevent; /* set sense data to no sense */ usbTargRbcSenseDataSet(SCSI_SENSE_NO_SENSE, SCSI_ADSENSE_NO_SENSE,0); return(OK); }/********************************************************************************* usbTargRbcVerify - verify the last data written to the RBC device** This routine verifies the last data written to the RBC block I/O device.** RETURNS: OK or ERROR.* * ERRNO:* none.*/STATUS usbTargRbcVerify ( UINT8 arg[10] /* the RBC command */ ) { /* * Assume last WRITE command was good. * set sense key to NO SENSE (0x0), * set additional sense code to NO ADDITIONAL SENSE INFORMATION */ usbTargRbcSenseDataSet(SCSI_SENSE_NO_SENSE, SCSI_ADSENSE_NO_SENSE,0); return(OK); }/********************************************************************************* usbTargRbcWrite - write to the RBC device** This routine writes to the RBC block I/O device.** RETURNS: OK or ERROR* * ERRNO:* none*/STATUS usbTargRbcWrite ( UINT8 arg[10], /* the RBC command */ UINT8 ** ppData, /* location where data will be written to device */ UINT32 *pSize /* size of location on device */ ) { UINT32 startLBA = 0; /* logical block address */ UINT16 xferLgth = 0; /* total length to write */ /* save starting LBA from arg[2] - arg[5]> save transfer length */ startLBA = (arg[2] << 24) | (arg[3] << 16) | (arg[4] << 8) | arg[5]; xferLgth = (arg[7] << 8) | arg[8]; /* pointer to where data is to be written */ *ppData = &g_dataOutBfr[0]; if ((xferLgth * BYTES_PER_BLOCK) < DATA_BUFFER_LEN) *pSize = xferLgth * BYTES_PER_BLOCK; else *pSize = DATA_BUFFER_LEN; usbTargRbcSenseDataSet(SCSI_SENSE_NO_SENSE, SCSI_ADSENSE_NO_SENSE, 0x0); return(OK); }/******************************************************************************** usbTargRbcInquiry - retrieve inquiry data from the RBC device** This routine retrieves inquiry data from the RBC block I/O device.** RETURNS: OK or ERROR* * ERRNO:* none*/STATUS usbTargRbcInquiry ( UINT8 cmd[6], /* the RBC command */ UINT8 **ppData, /* location of inquiry data on device */ UINT32 *pSize /* size of inquiry data on device */ ) { UINT8 evpd = cmd[1] & 0x1; /* enable vital product data bit */ UINT8 cmdDt = cmd[1] & 0x2; /* command support data bit */ UINT8 pageCode = cmd[2]; /* page code */ UINT8 allocLgth = cmd[4]; /* number of bytes of inquiry */ *ppData = NULL; *pSize = 0; if (evpd == 1) { /* return vital product data */ switch(pageCode) { case VPD_SUPPORTED_PAGE_CODE: /* return supported vital product data page codes: */ *ppData = (UINT8 *)&g_vpdSupportedPage; *pSize = sizeof(VPD_SUPPORTED_PAGE); break; case VPD_UNIT_SERIAL_NUM_PAGE_CODE: /* transmit vpdSerialNumPage */ *ppData = (UINT8 *)&g_vpdSerialNumPage; *pSize = sizeof(VPD_UNIT_SERIAL_NUM_PAGE); break; case VPD_DEVICE_ID_PAGE_CODE: /* transmit vpdDevIdPage */ *ppData = (UINT8 *)&g_vpdDevIdPage; *pSize = sizeof(VPD_DEVICE_ID_PAGE); break; default: /* * return ERROR status; set the sense key set to * ILLEGAL REQUEST and set the additional sense code * of INVALID FIELD IN CDB. */ usbTargRbcSenseDataSet (SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ADSENSE_INVALID_CDB,0); return(ERROR); } } else if (cmdDt == 1) { /* * return command support data. This implementation is optional; * therefore, the data returned will contain the peripheral qualifier, * device type byte, and 001b entered in the SUPPORT field. */ /* transmit cmdData */ *ppData = (UINT8 *)&g_cmdData; *pSize = sizeof(COMMAND_DATA); } else if (pageCode == 0) { /* return standard inquiry data must be at least 36 bytes */ *ppData = (UINT8 *)&g_stdInquiryData; *pSize = sizeof(STD_INQUIRY_DATA); } else { /* * return ERROR status with the sense key set to * ILLEGAL REQUEST and an additional sense code of * INVALID FIELD IN CDB. */ usbTargRbcSenseDataSet (SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ADSENSE_INVALID_CDB, 0); return(ERROR); } /* return only what was requested */ if (allocLgth < *pSize) *pSize = allocLgth; usbTargRbcSenseDataSet (SCSI_SENSE_NO_SENSE, SCSI_ADSENSE_NO_SENSE, 0x0); return(OK); }/********************************************************************************* usbTargRbcModeSelect - select the mode parameter page of the RBC device** This routine selects the mode parameter page of the RBC block I/O device.* For non-removable medium devices the SAVE PAGES (SP) bit shall be set to one. * This indicates that the device shall perform the specified MODE SELECT * operation and shall save, to a non-volatile vendor-specific location, all the* changeable pages, including any sent with the command. Application clients * should issue MODE SENSE(6) prior to each MODE SELECT(6) to determine supported* pages, page lengths, and other parameters.** RETURNS: OK or ERROR* * ERRNO:* none.*/STATUS usbTargRbcModeSelect ( UINT8 arg[6], /* the RBC command */ UINT8 ** ppData, /* location of mode parameter data on device */ UINT32 * pSize /* size of mode parameter data on device */ ) { UINT8 pgfmt = arg[0] & 0x10; /* page format */ UINT8 savePgs = arg[0] & 0x1; /* save pages */ UINT8 paramLstLgth = arg[4]; /* parameter list length */ /* * The removable media bit (RMB) in the stdInquiry data * page is one; therefore, support for the save pages bit * is optional */ if (pgfmt == 1 && savePgs == 0) { *ppData = (UINT8 *)&g_deviceParamList; *pSize = sizeof(MODE_PARAMETER_LIST); /* * return ERROR if paramLstLgth truncates any of the mode * parameter list (header and mode page). Set sense key to * ILLEGAL REQUEST, and ASC to PARAMETER LIST LENGTH ERROR. */ if (paramLstLgth < *pSize) { usbTargRbcSenseDataSet(SCSI_SENSE_ILLEGAL_REQUEST, SCSI_PARAMETER_LIST_LENGTH_ERROR, 0); return(ERROR); } } else { /* * set sense key to ILLEGAL REQUEST (05h) and an ASC of INVALID FIELD * IN CDB (24h). */ usbTargRbcSenseDataSet (SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ADSENSE_INVALID_CDB, 0); return(ERROR); } usbTargRbcSenseDataSet(SCSI_SENSE_NO_SENSE, SCSI_ADSENSE_NO_SENSE,0); return(OK); };/********************************************************************************* usbTargRbcModeSense - retrieve sense data from the RBC device** This routine retrieves sense data from the RBC block I/O device.** RETURNS: OK or ERROR* * ERRNO:* none.*/STATUS usbTargRbcModeSense ( UINT8 arg[6], /* the RBC command */ UINT8 ** ppData, /* location mode parameter data on device */ UINT32 * pSize /* size of mode parameter data on device */ ) { UINT8 pgCtrl = arg[2] & 0xc; /* page control feild */ UINT8 pgCode = arg[2] & 0x3f; /* page code */ UINT8 allocLgth = arg[4]; /* allocation length */ *ppData = NULL; *pSize = 0; if (pgCode == RBC_MODE_PARAMETER_PAGE) { switch (pgCtrl) { case 0: /* return current values */ case 2: /* return default values */ *ppData = (UINT8 *)&g_deviceParamList; *pSize = sizeof(MODE_PARAMETER_LIST); break; case 1: /* return changeable values */ /* * return a mask where the bit fields of the mode parameters * that are changeable shall are one; otherwise, zero. */ *ppData = (UINT8 *)&g_deviceParamListMask; *pSize = sizeof(MODE_PARAMETER_LIST); break; case 3: /* saved values are not implemented */ /* * termine with ERROR status, * set sense key set to ILLEGAL REQUEST * set additional sense code set to SAVING PARAMETERS * * NOT SUPPORTED. */ usbTargRbcSenseDataSet (SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ADSENSE_SAVE_ERROR, 0); return(ERROR); default: /* error */ /* * terminate with ERROR status, * set sense key set to ILLEGAL REQUEST * set additional sense code set to INVALID FIELD IN CDB. */ usbTargRbcSenseDataSet (SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ADSENSE_INVALID_CDB, 0); return(ERROR); } } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -