📄 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 + -