📄 disk_emu.c
字号:
disk_emu_tx_residue = data_len;
// printf("block_addr = %lu, data_len = %d\n", block_addr, data_len);
lseek(fd_disk, block_addr*BLOCK_SIZE, SEEK_SET);
disk_emu_state = DISK_EMU_DATA_IN;
// printf("state = DISK_EMU_DATA_IN\n");
data_len = ((disk_emu_tx_residue > RX_BUFFER_SIZE) ?
RX_BUFFER_SIZE : disk_emu_tx_residue);
data_len = read(fd_msdev, rcvd_data, data_len);
// printf("read nbytes = %x\n", data_len);
if(data_len) disk_emu_write(data_len);
break;
case CMD_REQUEST_SENSE:
/* Send the sense data */
res_len = REQUEST_SENSE_DATA_SIZE;
res_len = write(fd_msdev,request_sense_data, res_len);
disk_emu_tx_residue -= res_len;
disk_emu_prepare_sense_data(SENSE_KEY_NO_SENSE, 0x00, 0x00);
disk_emu_state = DISK_EMU_STATUS;
disk_emu_status(MSCD_CMD_RES_SUCCESS);
break;
case CMD_INQUIRY:
disk_emu_tx_residue = cmd[4];
res_len = (cmd[4] < INQUIRY_DATA_SIZE) ? cmd[4] : INQUIRY_DATA_SIZE;
if((cmd[1] & INQUIRY_EVPD) || cmd[2] ) {
/* If EVPD flags are set or Page code is not zero we are not
* supporting it */
disk_emu_prepare_sense_data(SENSE_KEY_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CDB,
0x00);
disk_emu_state = DISK_EMU_STATUS;
disk_emu_status(MSCD_CMD_RES_FAILED);
} else {
disk_emu_tx_residue -= write(fd_msdev,inquiry_data, res_len);
disk_emu_prepare_sense_data(SENSE_KEY_NO_SENSE, 0x00, 0x00);
disk_emu_state = DISK_EMU_STATUS;
disk_emu_status(MSCD_CMD_RES_SUCCESS);
}
break;
case CMD_TEST_UNIT_READY:
if(fd_disk) {
disk_emu_prepare_sense_data(SENSE_KEY_NO_SENSE, 0x00, 0x00);
disk_emu_state = DISK_EMU_STATUS;
disk_emu_status(MSCD_CMD_RES_SUCCESS);
} else {
disk_emu_prepare_sense_data(SENSE_KEY_NOT_READY, 0x00, 0x00);
disk_emu_state = DISK_EMU_STATUS;
disk_emu_status(MSCD_CMD_RES_FAILED);
}
break;
case CMD_START_STOP_UNIT:
if(cmd[4]&0x01) {
/* Start the UNIT */
if(fd_disk < 0) fd_disk = open(MSDISK_FILE, O_RDWR);
} else {
/* stop the unit */
if(fd_disk) close(fd_disk);
fd_disk = -1;
}
case CMD_FORMAT_UNIT:
case CMD_SEND_DIAGNOSTIC:
case CMD_VERIFY10:
disk_emu_prepare_sense_data(SENSE_KEY_NO_SENSE, 0x00, 0x00);
disk_emu_state = DISK_EMU_STATUS;
disk_emu_status(MSCD_CMD_RES_SUCCESS);
break;
case CMD_MEDIUM_REMOVAL:
prevent = cmd[4] & 0x01;
if(prevent && disk_emu_info.prevent) {
/* problem */
disk_emu_prepare_sense_data(SENSE_KEY_UNIT_ATTENTION, ASC_MEDIUM_CHANGE, 0x00);
disk_emu_state = DISK_EMU_STATUS;
disk_emu_status(MSCD_CMD_RES_FAILED);
} else {
disk_emu_info.prevent = (cmd[4] & 0x01);
lseek(fd_disk, LOGICAL_BLOCKS*BLOCK_SIZE, SEEK_SET);
write(fd_disk, (unsigned char*)(&disk_emu_info), sizeof(disk_emu_info_t));
disk_emu_prepare_sense_data(SENSE_KEY_NO_SENSE, 0x00, 0x00);
disk_emu_state = DISK_EMU_STATUS;
disk_emu_status(MSCD_CMD_RES_SUCCESS);
}
break;
case CMD_READ_CAPACITY:
if(!((cmd[8])& READ_CAPACITY_RMI)) {
res_len = READ_CAPACITY_DATA_SIZE;
disk_emu_tx_residue -= write(fd_msdev,read_capacity_data, res_len);
disk_emu_prepare_sense_data(SENSE_KEY_NO_SENSE, 0x00, 0x00);
disk_emu_state = DISK_EMU_STATUS;
disk_emu_status(MSCD_CMD_RES_SUCCESS);
} else {
res_len = -1;
disk_emu_prepare_sense_data( SENSE_KEY_ILLEGAL_REQUEST,
ASC_INV_FIELD_IN_CDB,
0x00);
}
break;
case CMD_MODE_SENSE:
res_len = MODE_SENSE_DATA_SIZE;
if(cmd[4] && cmd[4] < res_len) res_len = cmd[4];
disk_emu_tx_residue -= write(fd_msdev,mode_sense_data, res_len);
disk_emu_prepare_sense_data(SENSE_KEY_NO_SENSE, 0x00, 0x00);
disk_emu_state = DISK_EMU_STATUS;
disk_emu_status(MSCD_CMD_RES_SUCCESS);
break;
case CMD_RESERVE:
case CMD_RELEASE:
if(cmd[1] & RESERVE_EXTENT) {
disk_emu_prepare_sense_data(SENSE_KEY_ILLEGAL_REQUEST,
ASC_INV_FIELD_IN_CDB, 0x00);
disk_emu_state = DISK_EMU_STATUS;
disk_emu_status(MSCD_CMD_RES_FAILED);
} else {
disk_emu_prepare_sense_data(SENSE_KEY_NO_SENSE, 0x00, 0x00);
disk_emu_state = DISK_EMU_STATUS;
disk_emu_status(MSCD_CMD_RES_SUCCESS);
}
break;
default:
disk_emu_prepare_sense_data(SENSE_KEY_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CDB,
0x00);
disk_emu_state = DISK_EMU_STATUS;
sleep(1);
disk_emu_status(MSCD_CMD_RES_FAILED);
break;
}
return;
}
/*
* Send command response to the mass storage device
*/
void disk_emu_status(unsigned char status)
{
mscd_cmd_res_t cmd_res;
cmd_res.status = status;
cmd_res.residue = disk_emu_tx_residue;
ioctl(fd_msdev, MSCD_IOC_SET_CMD_RES, &cmd_res);
disk_emu_state = DISK_EMU_IDLE;
}
/*
* Signal handler
* This processes the signals received from the mass storage device
*/
void disk_emu_sighandler(int signo) {
unsigned int status, nbytes;
mscd_notif_t notif_sts;
int ret;
/*
* Get the Signal/notification from the device
*/
ret = ioctl(fd_msdev, MSCD_IOC_GET_NOTIF, ¬if_sts);
status = notif_sts.notif;
// printf("Singnal received %x \n",status);
switch (status) {
case MSCD_CMD:
// printf("MSCD_DATA_RCVD\n");
if(disk_emu_state == DISK_EMU_IDLE) {
ret = ioctl(fd_msdev, MSCD_IOC_GET_COMMAND, rcvd_data);
disk_emu_command();
} else if(disk_emu_state == DISK_EMU_DATA_IN) {
nbytes = read(fd_msdev,rcvd_data, disk_emu_tx_residue);
// printf("received bytes %d\n", nbytes);
disk_emu_write(nbytes);
}
break;
case MSCD_RESET:
// printf("MSCD_RESET\n");
/* This is reset mass storage device, reset the FSM */
disk_emu_info.prevent = 0;
lseek(fd_disk, LOGICAL_BLOCKS*BLOCK_SIZE, SEEK_SET);
nbytes = write(fd_disk, (unsigned char*)(&disk_emu_info), sizeof(disk_emu_info_t));
disk_emu_state = DISK_EMU_IDLE;
break;
default :
break;
}
return;
}
int main(int argc, char **argv)
{
int ret;
struct sigaction action;
int nbytes;
/* Open the mass storage device file */
fd_msdev=open(MS_DEV_FILE_NAME, O_RDWR);
if(fd_msdev < 0) {
printf("Error in opening file: %s\n",MS_DEV_FILE_NAME);
exit(0);
}
/* Open the mass storage disk emulation file */
fd_disk = open(MSDISK_FILE, O_RDWR);
if(fd_disk < 0) {
printf("disk emulation file is not found %s\n",MSDISK_FILE);
close(fd_msdev);
exit(0);
}
/* Initalize the status from the mass storage emulation file */
lseek(fd_disk, LOGICAL_BLOCKS*BLOCK_SIZE, SEEK_SET);
nbytes = read(fd_disk, (unsigned char*)(&disk_emu_info),sizeof(disk_emu_info_t));
if(nbytes != sizeof(disk_emu_info_t)) {
printf("Init file reading failed\n");
close(fd_disk);
close(fd_msdev);
exit(0);
}
close(fd_disk); /* Close the file temporarly */
fd_disk = -1;
/*
* Set signal action to receive asynchronous notifications from the
* mass storage device file
*/
memset(&action, 0, sizeof(action));
action.sa_handler = disk_emu_sighandler;
sigemptyset(&action.sa_mask);
action.sa_flags = 0;
sigaction(SIGIO, &action, NULL);
ret= fcntl(fd_msdev, F_SETOWN, getpid());
ret=fcntl(fd_msdev,F_GETFL);
fcntl(fd_msdev, F_SETFL, fcntl(STDIN_FILENO, F_GETFL) | FASYNC);
/*
* Wait for ever and process the things in signal handler
*/
while(1) {
/* Now the functionality of this depends on the singnal handler */
sleep(400);
}
if(fd_disk > 0) close(fd_disk);
close(fd_msdev);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -