📄 u_device.c
字号:
/****************************************************************************
* File name : device.c
* Module name : Device module
* Author : Hiromichi Kondo
*---------------------------------------------------------------------------
* $Id: device.c,v 1.2 2003/05/13 11:02:05 9551619 Exp $
****************************************************************************/
#include "c33l17.h"
#include "u_ram_data.h"
#include "u_rom_data.h"
#include "u_regNikka.h"
#include "u_value.h"
#include "usbmedia.h"
/*--- Function Prototype ---------------------------------------------------*/
void DeviceProc(void);
void WaitRcvCommand(void);
void CommandCheck(void);
void SetStatus(void);
void WaitCSWCmp(void);
void CBWCheck(void);
void CSWSet(void);
void InitDeviceWorkArea(void);
void MasterDMAStop(void);
void MasterDMAStart(void);
void MasterDMAXferEndProc(void);
/*****************************************************************************
* Device table
*****************************************************************************/
void (*const device_tbl[])() = {
WaitRcvCommand,
CommandCheck,
SetStatus,
WaitCSWCmp
};
void DeviceProc(void)
{
if( usb_state == CONFIGURED_STATE)
{
if (device_state > DEV_WAIT_CSW_CMP)
panic(5);
device_tbl[device_state]();
}
}
/*****************************************************************************
* WaitRcvCommand
*****************************************************************************/
void WaitRcvCommand(void)
{
if( device_flag.RcvCommand )
{
device_flag.RcvCommand = 0;
device_state = DEV_CMD_CHECK;
}
else
{
if( device_flag.WaitCBW )
{
if( tran_flag.XferCmp )
{
device_flag.WaitCBW = 0;
tran_flag.XferCmp = 0;
CBWCheck();
}
}
else
{
device_flag.WaitCBW = 1;
tran_flag.DMA = 0;
bulk_actual_tran_cnt = 31;
bulk_tran_start_addr = cbw;
bulk_out_state = BULK_OUT_DATA_GET;
}
}
}
/*****************************************************************************
* CommandCheck
*****************************************************************************/
void CommandCheck(void)
{
int ret;
int fifo_remain;
if( cmd_block[0] != 0x00 )
{
test_unit_ready_cnt = 0;
}
switch( cmd_block[0] ){
case 0x00: /* Test Unit Ready */
ret = TestUnitReady();
break;
case 0x03: /* Request Sense */
ret = RequestSense();
break;
case 0x12: /* Inquiry */
ret = Inquiry();
break;
case 0x1B: /* Start Stop Unit */
ret = StartStopUnit();
break;
case 0x1E: /* Prevent/Allow Medium Removal */
ret = Prevent();
break;
case 0x23: /* Read Format Capacity */
ret = ReadFormatCapacity();
break;
case 0x25: /* Read Capacity */
ret = ReadCapacity();
break;
case 0x28: /* Read(10) */
ret = Read10();
break;
case 0x2A: /* Write(10) */
ret = Write10();
break;
case 0x2B: /* Seek */
ret = Seek();
break;
case 0x2F: /* Verify */
ret = Verify();
break;
case 0x55: /* Mode Select */
ret = ModeSelect();
break;
case 0x5A: /* Mode Sense */
ret = ModeSense();
break;
default:
ret = CmdError();
}
if( ret == RC_OK )
{
if( bulk_total_tran_cnt == 0 )
{
protocol_phase = STATUS_PHASE;
tran_flag.XferCmp = 1;
}
else
{
protocol_phase = DATA_PHASE;
bulk_actual_tran_cnt = bulk_total_tran_cnt;
if( tran_flag.DMA )
MasterDMAStart();
if( tran_flag.Direction == DIR_IN )
bulk_in_state = BULK_IN_DATA_SET;
else
bulk_out_state = BULK_OUT_DATA_GET;
}
}
else
{
if( bulk_req_tran_cnt == 0 )
{
protocol_phase = STATUS_PHASE;
tran_flag.XferCmp = 1;
}
else
{
bulk_total_tran_cnt = 0;
protocol_phase = DATA_PHASE;
if( tran_flag.Direction == DIR_OUT )
{
rEPbControl_BP.ForceNAK = 1;
timer0_Wait(1);
rCPU_JoinRd_BP.JoinEPbRd = 1;
fifo_remain = MKWORD(rEPnRdRemain_H, rEPnRdRemain_L);
rCPU_JoinRd_BP.JoinEPbRd = 0;
if( bulk_req_tran_cnt <= fifo_remain )
{
rEPrFIFO_Clr_BP.EPbFIFO_Clr = 1;
protocol_phase = STATUS_PHASE;
tran_flag.XferCmp = 1;
}
else
{
rEPbControl_BP.ForceSTALL = 1;
bulk_out_state = BULK_OUT_STALL;
}
}
else
{
rEPaControl_BP.ForceSTALL = 1;
bulk_in_state = BULK_IN_STALL;
}
}
}
device_state = DEV_SET_STATUS;
}
/*****************************************************************************
* SetStatus
*****************************************************************************/
void SetStatus(void)
{
if( tran_flag.XferCmp )
{
if( protocol_phase == STATUS_PHASE )
{
tran_flag.XferCmp = 0;
rEPbControl_BP.ForceNAK = 1;
if( cmd_block[0] == 0x55 )
ModeSelParaCheck(); /* Mode Select */
CSWSet();
device_state = DEV_WAIT_CSW_CMP;
}
}
}
/*****************************************************************************
* WaitCSWCmp
*****************************************************************************/
void WaitCSWCmp(void)
{
if( tran_flag.XferCmp )
{
tran_flag.XferCmp = 0;
device_state = DEV_WAIT_RCV_CMD;
}
}
/*****************************************************************************
* CBWCheck
*****************************************************************************/
void CBWCheck(void)
{
int i, j;
if (cbw[0] != 0x55 || cbw[1] != 0x53 || cbw[2] != 0x42 || cbw[3] != 0x43)
{
rEPnControl_BP.EPrForceSTALL = 1;
bulk_in_state = BULK_IN_STALL;
bulk_out_state = BULK_OUT_STALL;
protocol_phase = RESET_WAIT;
}
else
{
bulk_req_tran_cnt = MKDWORD(cbw[11], cbw[10], cbw[9], cbw[8]);
tran_flag.Direction = ((cbw[12] & 0x80)? DIR_IN : DIR_OUT);
if (cbw[13])
{
rEPnControl_BP.EPrForceSTALL = 1;
bulk_in_state = BULK_IN_STALL;
bulk_out_state = BULK_OUT_STALL;
protocol_phase = RESET_WAIT;
}
else
{
for( i=0, j=15; i<cbw[14]; i++, j++ )
{
cmd_block[i] = cbw[j];
}
device_flag.RcvCommand = 1;
}
}
}
/*****************************************************************************
* CSWSet
*****************************************************************************/
void CSWSet(void)
{
int residue_cnt;
csw[4] = cbw[4];
csw[5] = cbw[5];
csw[6] = cbw[6];
csw[7] = cbw[7];
if (cmd_status != PHASE_ERROR)
{
residue_cnt = bulk_req_tran_cnt - bulk_total_tran_cnt;
csw[8] = DWORD2BYTE_LL(residue_cnt);
csw[9] = DWORD2BYTE_LH(residue_cnt);
csw[10] = DWORD2BYTE_HL(residue_cnt);
csw[11] = DWORD2BYTE_HH(residue_cnt);
}
else
{
csw[8] = 0x00;
csw[9] = 0x00;
csw[10] = 0x00;
csw[11] = 0x00;
}
csw[12] = cmd_status;
tran_flag.DMA = 0;
bulk_actual_tran_cnt = 13;
bulk_total_tran_cnt = bulk_req_tran_cnt;
bulk_tran_start_addr = csw;
bulk_in_state = BULK_IN_DATA_SET;
}
/*****************************************************************************
* InitDeviceWorkArea
*****************************************************************************/
void InitDeviceWorkArea(void)
{
int i;
tran_flag.XferCmp = 0;
tran_flag.Direction = DIR_OUT;
tran_flag.DMA = 0;
device_flag.RcvCommand = 0;
device_flag.WaitCBW = 0;
block_size = 512;
ata_lba = 0;
mode_data_cnt = 0;
bulk_tran_start_addr = 0;
mode_data_addr = 0;
mode_chg_addr = 0;
bulk_req_tran_cnt = 0;
bulk_total_tran_cnt = 0;
bulk_actual_tran_cnt = 0;
test_unit_ready_cnt = 0;
for (i = 0;i < 12;i++)
cmd_block[i] = 0;
for (i = 0;i < sizeof(wk_data);i++)
wk_data[i] = 0x00;
/* bCSWSignature */
csw[0] = 0x55;
csw[1] = 0x53;
csw[2] = 0x42;
csw[3] = 0x53;
/* Sense Key */
sense_data[0] = 0x00;
sense_data[1] = 0x00;
sense_data[2] = 0x00;
atten_flag.PowerOnReset = 1;
}
/*****************************************************************************
* MasterDMAStart
*****************************************************************************/
void MasterDMAStart(void)
{
pHS_EN(1) = 0; //HS1 disable
pHS_CNTLMODE = 1; //HSDMA ADV mode
pHS_EN(1) = 0; //HS1 disable
HSDxS(1) = 0x0d; //HS1 triggle src
pHS_TF(1) = 1; //HS1 triggle flag clear
DUALM(1) = 1; //HS1 dual address mode
DMOD(1) = 0; //HS1 single xfer mode
if ( tran_flag.Direction == DIR_IN )
{ /* IN xfer */
SADR_AD(1) = sram_start_addr ;
DADR_AD(1) = 0x00300A00;
SIN(1) = 3; //HS1 src inc
DIN(1) = 0; //HS1 des fix
}
else
{ /* OUT xfer */
SADR_AD(1) = 0x00300A00;
DADR_AD(1) = sram_start_addr ;
SIN(1) = 0; //HS1 src inc
DIN(1) = 3; //HS1 des fix
}
DATSIZE(1) = 0; //HS1 byte xfer
pHS_CNT(1) = bulk_actual_tran_cnt &0xffff; //HS1 xfer cnt low
TC_H(1) = (bulk_actual_tran_cnt>>16) &0xff;//HS1 xfer cnt high
INT_FHDM(1) = 1; //HS1 Int flag clear
pHS_EN(1) = 1; //HS1 enable
}
/*****************************************************************************
* MasterDMAStop
*****************************************************************************/
void MasterDMAStop(void)
{
pHS_EN(1) = 0; //HS1 disable
}
/*****************************************************************************
* MasterDMAXferEndProc
*****************************************************************************/
void MasterDMAXferEndProc(void)
{
int retVal = media_WriteSec(ata_lba, bulk_total_tran_cnt/block_size, &usb_wk_buf[0]);
if( retVal != 0 )
panic(42);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -