📄 disk_emu.c
字号:
/************************************************************* * Philips Mass Storage disk emulation * * (c) 2002 Koninklijke Philips Electronics N.V., All rights reserved * * This source code and any compilation or derivative thereof is the * proprietary information of Koninklijke Philips Electronics N.V. * and is confidential in nature. * Under no circumstances is this software to be exposed to or placed * under an Open Source License of any type without the expressed * written permission of Koninklijke Philips Electronics N.V. * * File Name: disk_emu.c * * History: * * Version Date Author Comments * ------------------------------------------------- * 1.0 09/23/02 SYARRA Initial Creation * *************************************************************/#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <signal.h>#include <fcntl.h>#include <sys/ioctl.h>#include "msbridge.h"#include "disk_emu.h"#define RX_BUFFER_SIZE 0x20000#define TX_BUFFER_SIZE 0x20000/*------------------------------------------------* * Global variable definitions * *------------------------------------------------*/int fd_msdev; /* Mass storage device file */int fd_disk; /* Disk emulation file */unsigned char disk_emu_state = DISK_EMU_IDLE; /* Disk emulation state */unsigned long disk_emu_tx_residue; /* Transfer residue */disk_emu_info_t disk_emu_info; /* Status *//* Transfer and receiver buffers */unsigned char rcvd_data[RX_BUFFER_SIZE];unsigned char disk_data[TX_BUFFER_SIZE];unsigned long tx_residue = 0;unsigned char inquiry_data[INQUIRY_DATA_SIZE] = { 0x00, 0x80, 0x02, 0x00, 0x33, 0x00, 0x00, 0x00, 'P', 'h', 'i', 'l', 'i', 'p', 's', ' ', 'O', 'T', 'G', ' ', 'M', 'a', 's', 's', ' ', 'S', 't', 'o', 'r', 'a', 'g', 'e', '1', '.', '0', '0'};unsigned char read_capacity_data[READ_CAPACITY_DATA_SIZE] = { ((LAST_LBA >>24) & 0xFF), /* block address */ ((LAST_LBA >>16) & 0xFF), ((LAST_LBA >>8) & 0xFF), (LAST_LBA & 0xFF), ((BLOCK_SIZE >> 24) & 0xFF), /* each block size (4 bytes) */ ((BLOCK_SIZE >> 16) & 0xFF), ((BLOCK_SIZE >> 8) & 0xFF), (BLOCK_SIZE & 0xFF)};unsigned char mode_sense_data[MODE_SENSE_DATA_SIZE] = { 0x0B, /* Length of this sense data */ 0x00, /* medium type */ 0x00, /* Device specific parameters */ 0x08, /* block descriptor length */ 0x00, /* density code */ ((LAST_LBA >>16) & 0xFF), /* Last Block address */ ((LAST_LBA >>8) & 0xFF), (LAST_LBA & 0xFF), 0x00, /* Reserved */ ((BLOCK_SIZE >> 16) & 0xFF), /* Block Size */ ((BLOCK_SIZE >> 8) & 0xFF), (BLOCK_SIZE & 0xFF)};unsigned char request_sense_data[REQUEST_SENSE_DATA_SIZE] = { 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };/*-----------------------------------------------------* * Local function declerations * *-----------------------------------------------------*/static void disk_emu_prepare_sense_data(unsigned char sense_key, unsigned char asc, unsigned char ascq);static void disk_emu_command(void);static void disk_emu_sighandler(int signo);static void disk_emu_status(unsigned char status);static int disk_emu_read(unsigned long data_len);static int disk_emu_write(unsigned long data_len);static void disk_emu_print_cmd(unsigned char *cmd);/*-----------------------------------------------------* * Local function definitions * *-----------------------------------------------------*/void disk_emu_print_cmd(unsigned char *cmd) { char cmd_name[30]; switch(cmd[0]) { case CMD_TEST_UNIT_READY: strcpy(cmd_name,"TEST_UNIT_READY "); break; case CMD_REQUEST_SENSE: strcpy(cmd_name,"REQUEST_SENSE "); break; case CMD_FORMAT_UNIT: strcpy(cmd_name,"CMD_FORMAT_UNIT"); break; case CMD_INQUIRY: strcpy(cmd_name,"INQUIRY "); break; case CMD_RESERVE: strcpy(cmd_name,"RESERVE "); break; case CMD_RELEASE: strcpy(cmd_name,"RELEASE "); break; case CMD_MODE_SENSE: strcpy(cmd_name,"MODE_SENSE "); break; case CMD_START_STOP_UNIT: strcpy(cmd_name,"START_STOP_UNIT "); break; case CMD_SEND_DIAGNOSTIC: strcpy(cmd_name,"SEND_DIAGNOSTIC "); break; case CMD_MEDIUM_REMOVAL: strcpy(cmd_name,"MEDIUM_REMOVAL "); break; case CMD_READ_CAPACITY: strcpy(cmd_name,"READ_CAPACITY "); break; case CMD_READ10: strcpy(cmd_name,"READ10 "); break; case CMD_WRITE10: strcpy(cmd_name,"WRITE10 "); break; case CMD_VERIFY10: strcpy(cmd_name,"VERIFY10 "); break; default: strcpy(cmd_name,"UNKNOWN COMMAND "); break; }// printf("%s received len = %d\n",cmd_name, cmd[14]);}void disk_emu_prepare_sense_data(unsigned char sense_key, unsigned char asc, unsigned char ascq) { request_sense_data[2] = sense_key; request_sense_data[12] = asc; request_sense_data[13] = ascq;}int disk_emu_read(unsigned long data_len){ unsigned long res_len, nbytes; unsigned char *data_ptr; /* Read from the emulation disk */ res_len = read(fd_disk, disk_data, data_len); if(res_len <=0) { disk_emu_prepare_sense_data( SENSE_KEY_MEDIUM_ERROR, ASC_ADDR_NOT_FOUND_4_ID_FLD, 0x00); disk_emu_state = DISK_EMU_STATUS; disk_emu_status(MSCD_CMD_RES_FAILED); return 0; } /* Write to the mass storage device */ data_ptr = disk_data; while(res_len) { nbytes = write(fd_msdev,data_ptr, res_len); data_ptr += nbytes; res_len -= nbytes; disk_emu_tx_residue -= nbytes; } if(disk_emu_tx_residue) { data_len = ((disk_emu_tx_residue > TX_BUFFER_SIZE) ? TX_BUFFER_SIZE : disk_emu_tx_residue); disk_emu_read(data_len); } 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); } return 0; }/* End of disk_emu_read */int disk_emu_write(unsigned long data_len){ unsigned long res_len; /* * This call will be a blocked one until we receive the * data from the host */ disk_emu_tx_residue -= data_len; /* Write to the emuation disk */ res_len = write(fd_disk, rcvd_data, data_len); if(res_len <=0 ) { disk_emu_prepare_sense_data( SENSE_KEY_MEDIUM_ERROR, ASC_ADDR_NOT_FOUND_4_ID_FLD, 0x00); } if(data_len != res_len) {// printf("read write error\n"); } if(!disk_emu_tx_residue) { disk_emu_state = DISK_EMU_STATUS; disk_emu_prepare_sense_data( SENSE_KEY_NO_SENSE, 0x00,0x00); disk_emu_status(MSCD_CMD_RES_SUCCESS); } else { data_len = ((disk_emu_tx_residue > RX_BUFFER_SIZE) ? RX_BUFFER_SIZE : disk_emu_tx_residue); if(data_len) disk_emu_write(data_len); } return 0;}/* End of disk_emu_write */void disk_emu_command(void) { unsigned char *cmd = rcvd_data; unsigned char cmd_type = cmd[0]; unsigned int data_len = 0; unsigned long block_addr; unsigned char prevent; long res_len = 0; disk_emu_print_cmd(cmd); disk_emu_state = DISK_EMU_CMD;// printf("state = DISK_EMU_CMD\n"); switch(cmd_type) { case CMD_READ10: block_addr = ((cmd[2] << 24) | (cmd[3] << 16) | (cmd[4] <<8) | cmd[5] ); data_len = ((cmd[7] << 8) | cmd[8]) *BLOCK_SIZE; disk_emu_tx_residue = data_len; if(fd_disk < 0) fd_disk = open(MSDISK_FILE, O_RDWR); if(disk_emu_tx_residue && (fd_disk != 1)) { /* Need to do more checking */ lseek(fd_disk, block_addr*BLOCK_SIZE, SEEK_SET); /* Some thing to be read from the disk emulation */ data_len = ((disk_emu_tx_residue > TX_BUFFER_SIZE) ? TX_BUFFER_SIZE : disk_emu_tx_residue); disk_emu_state = DISK_EMU_DATA_OUT;// printf("state = DISK_EMU_DATA_OUT\n"); disk_emu_read(data_len); } else {// printf("read call failed \n"); disk_emu_state = DISK_EMU_STATUS; disk_emu_status(MSCD_CMD_RES_FAILED); } break; case CMD_WRITE10: block_addr = ((cmd[2] << 24) | (cmd[3] << 16) | (cmd[4] <<8) | cmd[5] ); data_len = ((cmd[7] << 8) | cmd[8]) *BLOCK_SIZE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -