nt9856x/loader/Project/Model/Src/USB/usb_update.c

1232 lines
30 KiB
C
Executable File

//#include "board.h"
#include "fuart.h"
#include "usb_update.h"
#include "debug.h"
#include "timer.h"
#define IOADDR_USB_REG_BASE (0xFF600000)
#define _THUMB2 __attribute__((target("thumb2")))
_THUMB2 void fLib_USB_Update_FW(void);
int usbrom_exit = 0;
volatile DEV *ptusbdev;
#define ptotg ((volatile OTG200 *)IOADDR_USB_REG_BASE)
#define FUSB200_MAX_EP 8 // 1..10
#define FUSB200_MAX_FIFO 4 // 0.. 9
#define mUsbEPMap(EPn, MAP) (ptusbdev->ep_map[EPn-1] = MAP)
#define mUsbEPMapRd(EPn) (ptusbdev->ep_map[EPn-1])
#define mUsbFIFOMap(FIFOn, MAP) (ptusbdev->fifo_map[FIFOn] = MAP)
#define mUsbFIFOMapRd(FIFOn) (ptusbdev->fifo_map[FIFOn])
#define mUsbFIFOConfigRd(FIFOn) (ptusbdev->fifo_cfg[FIFOn])
static USB_st tusb;
static MassStorageState eUsbMassStorageState = MS_STATE_CBW;
CBW tCBW;
CSW tCSW;
SCSISense tSCSIsense;
SCSIDeviceResp tSCSIDeviceResp;
MSDC_Verify_CB guiU2MsdcCheck_cb;
MSDC_VenDone_CB guiU2MsdcVendorDone_cb;
int trigger_done_cb = 0;
static const unsigned char u8RequestSenseData[DATA_LENGTH_REQUEST_SENSE] __attribute__((aligned(4))) =
{
0x70, // 0, response code
0x00, // 1, obsolete
0x00, // 2, sense key
0x00, // 3-6, information
0x00,
0x00,
0x00,
0x0A, // 7, additional length (n - 7), n = 17
0x00, // 8-11, information
0x00,
0x00,
0x00,
0x00, // 12, additional sense code
0x00, // 13, additional sense code qualifier
0x00, // 14, field replaceable unit code
0x00, // 15-17, sense-key specific
0x00,
0x00
};
static const unsigned char u8ModeSenseData[DATA_LENGTH_MODE_SENSE] __attribute__((aligned(4))) =
{
0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
#define USB_BUFF_SZ 128
unsigned int u32Usb_buffer[USB_BUFF_SZ/4]; // may less than USB_BUFF_SZ
static INT32U nvtdev_opened = 1;
#define mCxType(cmd) ((cmd[0] & (BIT6 | BIT5)) >> 5)
#define mCxRequest(cmd) ((unsigned char)(cmd[0] >> 8))
#define mCxValue(cmd) ((unsigned short)(cmd[0] >> 16)) // get 3rd byte, 4th byte
#define mCxIndex(cmd) ((unsigned short)(cmd[1])) // get 5th byte, 6th byte
#define mCxLength(cmd) ((unsigned short)(cmd[1] >> 16)) // get 7th byte, 8th byte
#define mUsbRmWkupST() (ptusbdev->main_ctl & BIT0)
#define mUsbRmWkupClr() (ptusbdev->main_ctl &= ~BIT0)
#define mUsbRmWkupSet() (ptusbdev->main_ctl |= BIT0)
#define mUsbTsMdWr(item) (ptusbdev->phy_tms = item)
#define mUsbIntF2OUTDis() (ptusbdev->int_mgrp1 |= (BIT5 | BIT4))
#define mUsbIntF2OUTEn() (ptusbdev->int_mgrp1 &= ~(BIT5 | BIT4))
#define mUsbIntF0INDis() (ptusbdev->int_mgrp1 |= BIT16)
#define mUsbIntF0INEn() (ptusbdev->int_mgrp1 &= ~BIT16)
// Endpoint & FIFO Configuration
#define mUsbEPMxPtSz(EPn, dir, size) (ptusbdev->ep_xpsz[dir][EPn - 1] = size)
#define mUsbEPStallST(EPn, dir) (((ptusbdev->ep_xpsz[dir][EPn - 1]) & BIT11) >> 11)
#define mUsbEPRsTgSet(EPn, dir) (ptusbdev->ep_xpsz[dir][EPn-1] |= BIT12)
#define mUsbEPRsTgClr(EPn, dir) (ptusbdev->ep_xpsz[dir][EPn-1] &= ~BIT12)
#define mUsbEPStallClr(EPn, dir) (ptusbdev->ep_xpsz[dir][EPn-1] &= ~BIT11)
#define mUsbEPStallSet(EPn, dir) (ptusbdev->ep_xpsz[dir][EPn-1] |= BIT11)
extern void CPUflushReadCache(UINT32 uiStartAddr, UINT32 uiLength);
extern void CPUflushWriteCache(UINT32 uiStartAddr, UINT32 uiLength);
INT32S my_SCSICmd(CBW * ptcbw);
_THUMB2 signed int usb_DxFifoRdWr(unsigned char * buf, unsigned int count, unsigned int Rd)
{
signed int ret = -1; // assume fail
//#ifdef USBROM_RTOS_DBG
//debug_msg("MSG: enter usb_DxFifoRdWr\r\n");
//#endif
CPUflushWriteCache((UINT32) buf, (UINT32) count);
CPUflushReadCache((UINT32) buf, (UINT32) count);
//#ifdef __FREERTOS
//if(buf == (unsigned char *)0xFE080000)
// ptusbdev->dma_addr = (INT32U)buf;
//else
// ptusbdev->dma_addr = dma_getPhyAddr(buf);
//dma_flushWriteCache((UINT32)buf, count);
//dma_flushReadCache((UINT32)buf, count);
//#else
ptusbdev->dma_addr = (INT32U)buf;//dma_getPhyAddr(buf);
__asm__ __volatile__("dsb\n\t");
//#endif
if (Rd) {
// fifo select
ptusbdev->dma_fifo = BIT2;
// ctrl setting
ptusbdev->dma_ctl = (count << 8) | // dma byte count
(0 << 2) | // not dma io to io
(0 << 1); // fifo 2 memory
#ifdef USBROM_RTOS_DBG
debug_msg("MSG: count = %d, Read CTRL = %x\r\n", count, ptusbdev->dma_ctl);
#endif
} else {
// fifo select
ptusbdev->dma_fifo = BIT0;
// ctrl setting
ptusbdev->dma_ctl = (count << 8) | // dma byte count
(0 << 2) | // not dma io to io
(1 << 1); // memory 2 fifo
#ifdef USBROM_RTOS_DBG
debug_msg("MSG: Write count = %d, Write CTRL = %x\r\n", count, ptusbdev->dma_ctl);
#endif
}
// dma start
ptusbdev->dma_ctl |= BIT0;
while (1) {
INT32U temp;
temp = ptusbdev->int_grp2 & ~ ptusbdev->int_mgrp2;
if (temp & BIT7) { // dma completion
ret = 0; // ok
break;
}
if (temp & (BIT2 | BIT1)) { // bus condiction
// clear cx fifo
ptusbdev->cx_cf |= BIT3;
break;
}
if (temp & BIT8) { // dma error
// clear cx fifo
ptusbdev->cx_cf |= BIT3;
break;
}
}
// clear (dma error & dma completion) interrupt
ptusbdev->int_grp2 |= (BIT8 | BIT7);
CPUflushReadCache((UINT32) buf, (UINT32) count);
//debug_msg("done\r\n");
//#ifdef __FREERTOS
//dma_flushReadCache((UINT32)buf, count);
//#endif
return ret;
}
_THUMB2 void vSCSIHWError(void)
{
tCSW.u8Status = CSW_STATUS_CMD_FAIL;
if ((tCBW.CB0_cblen_lun_flag&0xFF) == CBW_FLAG_OUT) {
mUsbEPStallSet(OUT_EP, DIRECTION_OUT);
} else {
//debug_msg("S1\r\n");
mUsbEPStallSet(IN_EP, DIRECTION_IN);
}
//#ifdef USBROM_RTOS_DBG
//DBG_DUMP("MSG: vSCSIHWError\r\n");
//#endif
tSCSIsense.u8Key = KEY_NOT_READY;
tSCSIsense.u8KeyAdd = ADDKEY_MEDIUM_NOT_PRESENT;
}
//////////////////////////////////////////////////////////////////////////////////
_THUMB2 MassStorageState eScsiIn(void)
{
switch (tSCSIDeviceResp.u8MemIndex) {
case CARD_INDEX_SRAM:
// unit: byte
if (usb_DxFifoRdWr((INT8U *)u32Usb_buffer, tSCSIDeviceResp.u16DataResidue, 0) >= 0) {
tCSW.u32DataResidue -= tSCSIDeviceResp.u16DataResidue;
if (tCSW.u32DataResidue) {
// wait for fifo empty
while ((ptusbdev->cx_cf & (BIT8 | BIT9)) != (BIT8 | BIT9)) {
// if (VBUS == 0)
// return MS_STATE_CSW;
}
//debug_msg("S2\r\n");
//mUsbEPStallSet(IN_EP, DIRECTION_IN); // case MS13Case_5:
}
return MS_STATE_CSW;
}
break;
case CARD_INDEX_FSM_SS:
if (usb_DxFifoRdWr((INT8U *)tSCSIDeviceResp.u32IOAddr, tSCSIDeviceResp.u16DataResidue, 0) >= 0) {
tCSW.u32DataResidue -= tSCSIDeviceResp.u16DataResidue;
return MS_STATE_CSW;
} else {
mUsbEPStallSet(OUT_EP, DIRECTION_IN); // case MS13Case_11:
}
break;
default:
break;
}
vSCSIHWError();
return MS_STATE_CSW;
}
//////////////////////////////////////////////////////////////////////////////////
_THUMB2 MassStorageState eScsiOut(void)
{
switch (tSCSIDeviceResp.u8MemIndex) {
case CARD_INDEX_SRAM:
if (usb_DxFifoRdWr((INT8U *)u32Usb_buffer, tSCSIDeviceResp.u16DataResidue, 1) >= 0) {
tCSW.u32DataResidue -= tSCSIDeviceResp.u16DataResidue;
if (tCSW.u32DataResidue)
mUsbEPStallSet(OUT_EP, DIRECTION_OUT); // case MS13Case_11:
return MS_STATE_CSW;
}
break;
case CARD_INDEX_FSM_SS:
if (usb_DxFifoRdWr((INT8U *)tSCSIDeviceResp.u32IOAddr, tSCSIDeviceResp.u16DataResidue, 1) >= 0) {
tCSW.u32DataResidue -= tSCSIDeviceResp.u16DataResidue;
return MS_STATE_CSW;
} else {
mUsbEPStallSet(OUT_EP, DIRECTION_OUT); // case MS13Case_11:
}
break;
default:
break;
}
vSCSIHWError();
return MS_STATE_CSW;
}
typedef unsigned int size_t;
extern void *utl_memcpy(void *dest, const void *src, size_t count);
_THUMB2 void vSCSICmd_RequestSense(void)
{
// Device intend to send data
tSCSIDeviceResp.u8Flags = CBW_FLAG_IN;
tSCSIDeviceResp.u8MemIndex = CARD_INDEX_SRAM;
tSCSIDeviceResp.u16DataResidue = sizeof(u8RequestSenseData);
// copy response to sram
utl_memcpy ((UINT32 *)u32Usb_buffer, (UINT32 *)u8RequestSenseData, (UINT32)sizeof(u8RequestSenseData));
*((unsigned int *)u32Usb_buffer + (SENSE_OFFSET_KEY>>2)) += (tSCSIsense.u8Key&0xFF)<<16;
*((unsigned int *)u32Usb_buffer + (SENSE_OFFSET_ADD>>2)) += (tSCSIsense.u8KeyAdd&0xFF);
// all key disappear
tSCSIsense.u8Key = KEY_NO_SENSE;
tSCSIsense.u8KeyAdd = ADDKEY_NO_ADDITIONAL;
}
_THUMB2 void vSCSICmd_ModeSense(void)
{
//switch (tCBW.u8CB[2]) {
switch ((tCBW.CB1_CB15[0]>>8)&0xFF) {
case 0x00: // return mode parameter header and block descriptor
//debug_msg("MODE_SENSE 00\r\n");
tSCSIDeviceResp.u16DataResidue = 0x0C;
break;
case 0x3F: // all pages
//debug_msg("MODE_SENSE 3F\r\n");
tSCSIDeviceResp.u16DataResidue = sizeof(u8ModeSenseData);
break;
default:
//debug_msg("MODE_SENSE ERR\r\n");
tSCSIsense.u8Key = KEY_ILLEGAL_REQUEST;
tSCSIsense.u8KeyAdd = ADDKEY_INVALID_FIELD_IN_CMD;
tCSW.u8Status = CSW_STATUS_CMD_FAIL;
return;
}
// Device intend to send data
tSCSIDeviceResp.u8Flags = CBW_FLAG_IN;
tSCSIDeviceResp.u8MemIndex = CARD_INDEX_SRAM;
// copy response to sram
utl_memcpy((UINT32 *)u32Usb_buffer, (UINT32 *)u8ModeSenseData, (UINT32)tSCSIDeviceResp.u16DataResidue);
}
_THUMB2 void vSCSICmd_Unsupport(void)
{
// Device intend to transfer no data
tSCSIsense.u8Key = KEY_ILLEGAL_REQUEST;
tSCSIsense.u8KeyAdd = ADDKEY_INVALID_CMD_OP_CODE;
tCSW.u8Status = CSW_STATUS_CMD_FAIL;
//#ifdef DISPLAY_USB_INFORMATION
//DBG_DUMP("MSG: UnSupported SCSI Command (op code = 0x%x)\r\n", tCBW.u8CB[0]);
//#endif
}
_THUMB2 MassStorageState eMassStorage13case(void)
{
MassStorage13Case eCase = 0x0;
MassStorageState estate;
INT32U u32DeviceRespDataLength = 0x0;
switch(tSCSIDeviceResp.u8MemIndex) {
case CARD_INDEX_SRAM:
u32DeviceRespDataLength = tSCSIDeviceResp.u16DataResidue;
tSCSIDeviceResp.u32IOAddr += tSCSIDeviceResp.u16TfSzCurrent;
break;
case CARD_INDEX_FSM_SS:
u32DeviceRespDataLength = tSCSIDeviceResp.u16DataResidue;
break;
default:// SPI
u32DeviceRespDataLength = tSCSIDeviceResp.u16DataResidue * 2112;
break;
}
// Mass Storage the thirteen case
if (tCBW.u32DataTransferLength == u32DeviceRespDataLength) {
// normal case
if (tCBW.u32DataTransferLength == 0)
eCase = MS13Case_1; // MassStorage case (1)
else {
if ((tCBW.CB0_cblen_lun_flag&0xFF) == tSCSIDeviceResp.u8Flags) {
if ((tCBW.CB0_cblen_lun_flag&0xFF) == CBW_FLAG_IN)
eCase = MS13Case_6; // MassStorage case (6)
else
eCase = MS13Case_12; // MassStorage case (12)
}
}
//#ifdef DISPLAY_USB_INFORMATION
// vShowSCSI();
//#endif
} else {
if (tCBW.u32DataTransferLength == 0)
eCase = MS13Case_2_3; // MassStorage case (2)(3)
else if ((tCBW.CB0_cblen_lun_flag&0xFF) == CBW_FLAG_IN) {
if (u32DeviceRespDataLength == 0)
eCase = MS13Case_4; // MassStorage case (4)
else if (tSCSIDeviceResp.u8Flags == CBW_FLAG_IN) {
if (tCBW.u32DataTransferLength > u32DeviceRespDataLength)
eCase = MS13Case_5; // MassStorage case (5)
else
eCase = MS13Case_7_8; // MassStorage case (7)(8)
}
}
else { //tCBW.u8Flags == CBW_FLAG_OUT
if (u32DeviceRespDataLength == 0)
eCase = MS13Case_9; // MassStorage case (9)
else if (tSCSIDeviceResp.u8Flags == CBW_FLAG_OUT) {
if (tCBW.u32DataTransferLength > u32DeviceRespDataLength)
eCase = MS13Case_11; // MassStorage case (11)
else
eCase = MS13Case_10_13; // MassStorage case (10)(13)
}
}
//#ifdef DISPLAY_USB_INFORMATION
// {
//vShowUsb();
// DBG_DUMP("MSG: MS13Case = 0x%x\r\n", eCase);
// DBG_DUMP("MSG: , u32DeviceRespDataLength = 0x%x\r\n", u32DeviceRespDataLength);
// }
//#endif
}
// assume the next state is STATE_CSW
estate = MS_STATE_CSW;
switch (eCase) {
case MS13Case_2_3:
//debug_msg("S3\r\n");
mUsbEPStallSet(IN_EP, DIRECTION_IN);
tCSW.u8Status = CSW_STATUS_PHASE_ERROR;
break;
case MS13Case_4:
//debug_msg("S4\r\n");
mUsbEPStallSet(IN_EP, DIRECTION_IN);
break;
case MS13Case_5:
case MS13Case_6:
estate = eScsiIn();
break;
case MS13Case_11:
case MS13Case_12:
estate = eScsiOut();
break;
case MS13Case_7_8:
//debug_msg("S5\r\n");
mUsbEPStallSet(IN_EP, DIRECTION_IN);
tCSW.u8Status = CSW_STATUS_PHASE_ERROR;
break;
case MS13Case_9:
mUsbEPStallSet(OUT_EP, DIRECTION_OUT);
break;
case MS13Case_10_13:
mUsbEPStallSet(OUT_EP, DIRECTION_OUT);
tCSW.u8Status = CSW_STATUS_PHASE_ERROR;
//debug_msg("S6\r\n");
mUsbEPStallSet(IN_EP, DIRECTION_IN);
break;
default: // MS13Case_1;
// do nothing here
break;
}
return estate;
}
_THUMB2 MassStorageState eSCSI_CmdDecode(void) //trace, different from FUSB100-CardReader
{
//debug_msg("eSCSI_CmdDecode\r\n");
// Assume SCSI Response data length will be 0
tSCSIDeviceResp.u16DataResidue = 0;
if (((tCBW.CB0_cblen_lun_flag >> 8)&0xFF) >= CARD_TYPE_MAX_REPORT) {
tCSW.u8Status = CSW_STATUS_CMD_FAIL;
tSCSIsense.u8Key = KEY_NOT_READY;
tSCSIsense.u8KeyAdd = ADDKEY_LOGICAL_UNIT_NOT_SUPPORT;
} else {
// Parse SCSI command
//switch (tCBW.u8CB[0]) { // Operation Code
switch ((tCBW.CB0_cblen_lun_flag >> 24)&0xFF) { // Operation Code
case SCSI_OP_REQUEST_SENSE:
vSCSICmd_RequestSense();
//debug_msg("vSCSICmd_RequestSense\r\n");
break;
case SCSI_OP_MEDIUM_REMOVAL:
//vSCSICmd_MediumRemoval();
debug_msg("SCSI_OP_MEDIUM_REMOVAL\r\n");
break;
case SCSI_OP_INQUIRY:
//vSCSICmd_Inquiry();
debug_msg("SCSI_OP_INQUIRY\r\n");
break;
case SCSI_OP_MODE_SENSE:
vSCSICmd_ModeSense();
//debug_msg("SCSI_OP_MODE_SENSE 22\r\n");
break;
case SCSI_OP_TEST_UNIT_READY:
case SCSI_OP_READ_CAPACITY:
case SCSI_OP_READ_10:
case SCSI_OP_WRITE_10:
case SCSI_OP_VERIFY:
//debug_msg("SCSI_OP_TEST_UNIT_READY\r\n");
tSCSIsense.u8Key = KEY_NOT_READY;
tSCSIsense.u8KeyAdd = ADDKEY_MEDIUM_NOT_PRESENT;
tCSW.u8Status = CSW_STATUS_CMD_FAIL;
break;
default:
if (my_SCSICmd(&tCBW) < 0) {
//#ifdef USBROM_RTOS_DBG
debug_msg("MSG: SCSI cmd: UNSUPPOR\r\n");
//#endif
vSCSICmd_Unsupport();
}
break;
}
}
return eMassStorage13case();
}
_THUMB2 MassStorageState eUsbProessCBW(void)
{
usb_DxFifoRdWr((unsigned char *)&tCBW, 31, 1);
if(tCBW.u32Signature != CBW_SIGNATE) {
return MS_STATE_CBW;
} else {
// pass u32DataTransferLength to u32DataResidue
tCSW.u32DataResidue = tCBW.u32DataTransferLength;
#ifdef USBROM_RTOS_DBG
//DBG_DUMP("MSG: tCSW.u32DataResidue = %d, dir = %d\r\n", tCBW.u32DataTransferLength, tCBW.u8Flags);
#endif
// pass Tag from CBW to CSW
tCSW.u32Tag = tCBW.u32Tag;
// Assume Status is CMD_PASS
tCSW.u8Status = CSW_STATUS_CMD_PASS;
return eSCSI_CmdDecode();
}
}
_THUMB2 void vUsbUnplug(void)
{
//#ifdef USBROM_RTOS_DBG
//debug_msg("MSG: Unplug.. pls check\r\n");
//#endif
// mUsbUnPlug();
ptusbdev->phy_tms |= BIT0;
}
_THUMB2 void vUsb_BulkIntOnOff(void)
{
//#ifdef USBROM_RTOS_DBG
//DBG_DUMP("MSG: st 0x%x", eUsbMassStorageState);
//#endif
switch(eUsbMassStorageState)
{
case MS_STATE_CBW:
mUsbIntF2OUTEn();
mUsbIntF0INDis();
break;
case MS_STATE_CB_DMA_IN:
if (mUsbEPStallST (IN_EP, DIRECTION_IN)) {
// wait for clear feature, and then enable F0
}
else
mUsbIntF0INEn();
break;
case MS_STATE_CB_DMA_OUT:
mUsbIntF2OUTEn();
break;
case MS_STATE_CSW:
mUsbIntF2OUTDis();
if (mUsbEPStallST (IN_EP, DIRECTION_IN)) {
// wait for clear feature, and then enable F0
}
else {
mUsbIntF0INEn();
}
break;
case MS_STATE_BGD:
mUsbIntF2OUTDis();
mUsbIntF0INDis();
break;
default:
//#ifdef USBROM_RTOS_DBG
debug_msg("MSG: Error MS_STATE\r\n");
//#endif
vUsbUnplug();
break;
}
}
_THUMB2 void vUsb_F0_In(void)
{
switch(eUsbMassStorageState)
{
case MS_STATE_CSW:
//#ifdef USBROM_RTOS_DBG
//debug_msg("MSG: EP1 IN CSW\r\n");
//#endif
if (trigger_done_cb) {
trigger_done_cb = 0;
if (guiU2MsdcVendorDone_cb != NULL) {
if (guiU2MsdcVendorDone_cb((unsigned int)&tCBW) != 0) {
tCSW.u8Status = CSW_STATUS_CMD_FAIL;
}
}
}
usb_DxFifoRdWr((unsigned char *)&tCSW, 13, 0);
//mUsbFIFODone(FIFO0);
eUsbMassStorageState = MS_STATE_CBW;
if(usbrom_exit == 1)
usbrom_exit = 2;
break;
case MS_STATE_CB_DMA_IN:
//#ifdef USBROM_RTOS_DBG
//debug_msg("MSG: EP1 CS DMA IN\r\n");
//#endif
eUsbMassStorageState = eScsiOut();
break;
default:
//#ifdef USBROM_RTOS_DBG
debug_msg("MSG: Error FIFO0_IN interrupt.\r\n");
//#endif
break;
}
vUsb_BulkIntOnOff();
}
_THUMB2 void vUsb_F2_Out(unsigned int u32FIFOByteCount)
{
switch(eUsbMassStorageState) {
case MS_STATE_CBW:
//#ifdef USBROM_RTOS_DBG
//debug_msg("MSG: EP2 Out CBW\r\n");
//#endif
if (u32FIFOByteCount == 31) {
eUsbMassStorageState = eUsbProessCBW();
}
else{
//#ifdef USBROM_RTOS_DBG
//debug_msg("MSG: EP out STAL SET\r\n");
//#endif
mUsbEPStallSet(OUT_EP, DIRECTION_OUT);
}
break;
case MS_STATE_CB_DMA_OUT:
//#ifdef USBROM_RTOS_DBG
//debug_msg("MSG: EP2 Out CB DMA Out\r\n");
//#endif
eUsbMassStorageState = eScsiOut();
break;
default:
//#ifdef USBROM_RTOS_DBG
//debug_msg("MSG: Error FIFO2_OUT interrupt.\r\n");
//#endif
break;
}
vUsb_BulkIntOnOff();
}
///////////////////////////////////////////////////////////////////////////////
// bClear_feature()
// Description:
// 1. Send 2 bytes status to host.
// input: none
// output: TRUE or FALSE (BOOLEAN)
///////////////////////////////////////////////////////////////////////////////
_THUMB2 signed int usb_Clear_feature(void)
{
unsigned int ep_n;
unsigned int fifo_n;
signed int bdir;
switch (mCxValue (tusb.u32UsbCmd)) { // FeatureSelector
case 0: // ENDPOINT_HALE
// Clear "Endpoint_Halt", Turn off the "STALL" bit in Endpoint Control Function Register
if(mCxIndex (tusb.u32UsbCmd) == 0x00)
tusb.bUsbEP0HaltSt = FALSE;
else {
ep_n = mCxIndex (tusb.u32UsbCmd) & 0x7F; // which ep will be clear
// over the Max. ep count ?
if (ep_n > FUSB200_MAX_EP)
return -1;
// the direction of this ep
// bdir =0 if OUT
bdir = mCxIndex (tusb.u32UsbCmd) & BIT7;;
// get the relatived FIFO number
if (bdir)
fifo_n = mUsbEPMapRd(ep_n) & 0x0F;
else
fifo_n = mUsbEPMapRd(ep_n) >> 4;
// over the Max. fifo count ?
if (fifo_n >= FUSB200_MAX_FIFO)
return -1;
// Check the FIFO had been enable ?
if ((mUsbFIFOConfigRd(fifo_n) & BIT5) == 0)
return -1;
// bdir =0 if IN, 1 if OUT
bdir = bdir ? 0: 1;
mUsbEPRsTgSet(ep_n, bdir); // Set Rst_Toggle Bit
mUsbEPRsTgClr(ep_n, bdir); // Clear Rst_Toggle Bit
mUsbEPStallClr(ep_n, bdir); // Clear Stall Bit
vUsb_BulkIntOnOff();
}
break;
case 1 : // Device Remote Wakeup
// Clear "Device_Remote_Wakeup", Turn off the"RMWKUP" bit in Main Control Register
mUsbRmWkupClr();
break;
case 2 : // Test Mode
// do not break here
default :
return -1;
}
tusb.eUsbCxAction = ACT_DONE;
return 0;
}
_THUMB2 signed int usb_StandardCommand(void)
{
switch (mCxRequest (tusb.u32UsbCmd)) { // by Standard Request codes
//case 0: // get status
// return (usb_Get_status());
case 1: // clear feature
return (usb_Clear_feature());
//case 3: // set feature
// return (usb_Set_feature());
//case 5: // set address
// if (!tusb.bUsbEP0HaltSt)
// return(usb_Set_address());
// break;
//case 6: // get descriptor
// if (!tusb.bUsbEP0HaltSt)
// return(usb_Get_descriptor());
// break;
//case 8: // get configuration
// if (!tusb.bUsbEP0HaltSt)
// vGet_configuration();
// return 0;
//case 9: // set configuration
// if (!tusb.bUsbEP0HaltSt)
// return(usb_Set_configuration());
// break;
//case 10: // get interface
// if (!tusb.bUsbEP0HaltSt)
// return(usb_Get_interface());
// break;
// case 11: // set interface
// if (!tusb.bUsbEP0HaltSt)
// return(usb_Set_interface());
// break;
case 2: // Reserved for further use
case 4: // Reserved for further use
case 7: // set descriptor, not support
case 12: // synch frame, not support
default:
break;
}
return -1;
}
///////////////////////////////////////////////////////////////////////////////
// vUsb_ep0setup()
// Description:
// 1. Read 8-byte setup packet.
// 2. Decode command as Standard, Class, Vendor or NOT support command
// input: none
// output: none
///////////////////////////////////////////////////////////////////////////////
_THUMB2 void vUsb_ep0setup(void)
{
/*
if(tusb.bUsbChirpFinish == 0)
{
// first ep0 command after usb reset, means we can check usb speed right now.
tusb.bUsbChirpFinish = 1;
if (ptusbdev->main_ctl & BIT6) {
tusb.bHighSpeed = 1;
//DBG_DUMP("MSG: L%x, high speed mode\r\n", tusb.u8LineCount ++);
}
else {
tusb.bHighSpeed = 0;
//DBG_DUMP("MSG: L%x, full speed mode\r\n", tusb.u8LineCount ++);
}
// Init AP
vUsbMassStorageInit();
}
*/
// select dma target fifo no.:
//ptusbdev->dma_fifo = BIT4;
// Read 8-byte setup packet from FIFO
tusb.u32UsbCmd[0] = ptusbdev->dma_data;
tusb.u32UsbCmd[1] = ptusbdev->dma_data;
#if 0//def USBROM_RTOS_DBG
DBG_DUMP("MSG: L%x, EP0Cmd: %x %x %x %x %x %x %x %x\r\n",
tusb.u8LineCount ++, (INT8U)(tusb.u32UsbCmd[0] >> 0)
, (INT8U)(tusb.u32UsbCmd[0] >> 8)
, (INT8U)(tusb.u32UsbCmd[0] >> 16)
, (INT8U)(tusb.u32UsbCmd[0] >> 24)
, (INT8U)(tusb.u32UsbCmd[1] >> 0)
, (INT8U)(tusb.u32UsbCmd[1] >> 8)
, (INT8U)(tusb.u32UsbCmd[1] >> 16)
, (INT8U)(tusb.u32UsbCmd[1] >> 24));
#endif
// Command Decode
switch (mCxType(tusb.u32UsbCmd)) {
case 0: // standard command
//#ifdef USBROM_RTOS_DBG
//DBG_DUMP("MSG: Standard command\r\n");
//#endif
if (usb_StandardCommand() < 0)
tusb.eUsbCxAction = ACT_STALL;
break;
/*
case 1: // class command
#ifdef USBROM_RTOS_DBG
DBG_DUMP("MSG: class command\r\n");
#endif
if (usb_ClassCommand() < 0)
tusb.eUsbCxAction = ACT_STALL;
break;
case 2: // vendor command
#ifdef USBROM_RTOS_DBG
DBG_DUMP("MSG: vendor command\r\n");
#endif
// if (usb_UsbVendorCommand() < 0
tusb.eUsbCxAction = ACT_STALL;
break;
*/
default:
// Invalid(bad) command, Return EP0_STALL flag
tusb.eUsbCxAction = ACT_STALL;
break;
}
}
_THUMB2 void vUsbInit(void)
{
ptusbdev = ((volatile DEV *)(IOADDR_USB_REG_BASE + 0x100));
// init variables
tusb.eUsbCxAction = ACT_IDLE;
tusb.bUsbChirpFinish = 0;
tusb.u16TxRxCounter = 0;
tusb.eUsbCxCommand = CMD_VOID;
tusb.u8UsbConfigValue = 0;
tusb.u8UsbInterfaceValue = 0;
tusb.u8UsbInterfaceAlternateSetting = 0;
tusb.bUsbEP0HaltSt = FALSE;
// init hardware
//vFUSB200Init();
tusb.u8LineCount = 1;
tCSW.u32Signature = CSW_SIGNATE;
eUsbMassStorageState = MS_STATE_CBW;
mUsbIntF2OUTEn ();
mUsbIntF0INDis();
}
_THUMB2 void vUsbIsr2(void)
{
INT32U level1;
INT32U level2;
level1 = ptusbdev->int_grp & ~ ptusbdev->int_mgrp;
if (0 == level1)
return;
if (level1 & BIT2) { //Group 2
level2 = ptusbdev->int_grp2 & ~ ptusbdev->int_mgrp2;
if (level2) {
//debug_msg("MSG: IntSCR2\r\n");
if (level2 & BIT0) {
//debug_msg("MSG: BUS RST\r\n");
}
if (level2 & BIT1) {
//debug_msg("MSG: BUS SUSPEND\r\n");
ptusbdev->int_grp2 |= BIT1;
}
if (level2 & BIT2) {
//debug_msg("MSG: BUS RESUME\r\n");
ptusbdev->int_grp2 |= BIT2;
}
if (level2 & BIT5) {
//debug_msg("MSG: TX0B\r\n");
ptusbdev->tx0byte |= 0;
ptusbdev->int_grp2 |= BIT5;
}
if (level2 & BIT6) {
//debug_msg("MSG: RX0B\r\n");
ptusbdev->rx0byte |= 0;
ptusbdev->int_grp2 |= BIT6;
}
}
}
if (level1 & BIT0) { //Group 0
level2 = ptusbdev->int_grp0 & ~ ptusbdev->int_mgrp0;
if (level2) {
//debug_msg("MSG: IntSCR0\r\n");
if (level2 & BIT0) {
//debug_msg("MSG: USB ep0 Setup\r\n");
vUsb_ep0setup();
}
else if (level2 & BIT3) {
//debug_msg("MSG: USB ep0 end\r\n");
//vUsb_ep0end();
}
if (level2 & BIT1) {
//debug_msg("MSG: USB ep0 TX\r\n");
//vUsb_ep0tx();
}
if (level2 & BIT2) {
//#ifdef USBROM_RTOS_DBG
//debug_msg("MSG: USB ep0 RX\r\n");
//#endif
//vUsb_ep0rx();
}
if (level2 & BIT4) {
//#ifdef USBROM_RTOS_DBG
//debug_msg("MSG: USB ep0 fail\r\n");
//#endif
// stall cx: mUsbEP0StallSet();
//ptusbdev->cx_cf |= BIT2;
}
if (level2 & BIT5) {
//#ifdef USBROM_RTOS_DBG
//debug_msg("MSG: cmd abort\r\n");
//#endif
ptusbdev->int_grp0 |= BIT5;
}
}
if (tusb.eUsbCxAction == ACT_STALL) {
ptusbdev->cx_cf |= BIT2;
//#ifdef USBROM_RTOS_DBG
//DBG_DUMP("MSG: EP0 STALL\r\n");
//#endif
}
else if (tusb.eUsbCxAction == ACT_DONE) {
ptusbdev->cx_cf |= BIT0;
//#ifdef USBROM_RTOS_DBG
//DBG_DUMP("MSG: EP0 DONE\r\n");
//#endif
}
// Clear Action
tusb.eUsbCxAction = ACT_IDLE;
}
if (level1 & BIT1) { //Group Byte 1
level2 = ptusbdev->int_grp1 & ~ ptusbdev->int_mgrp1;
//#ifdef USBROM_RTOS_DBG
//debug_msg("MSG: IntSCR1\r\n");
//#endif
if (level2 & (BIT5 | BIT4)) { // F2 out (full or short)
vUsb_F2_Out(ptusbdev->fifo_bc[2]);
}
if (level2 & BIT16) // F0 in
vUsb_F0_In();
}
}
_THUMB2 static INT32U calc_sum_v2(INT32U dat0, INT32U dat1, INT32U dat2, INT32U dat3)
{
INT32U sum=0;
sum = (dat0&0xFFFF)+((dat0>>16))+(dat1&0xFFFF)+((dat1>>16)) +
(dat2&0xFFFF)+((dat2>>16))+(dat3&0xFFFF)+((dat3>>16)) + 28;
//DBG_DUMP("SUM = 0x%08X\r\n",sum);
return sum&0xFFFF;
}
_THUMB2 INT32S my_SCSICmd(CBW * ptcbw)
{
INT32U temp1, temp2;
INT32U CDB[4];
CDB[0] = ((ptcbw->CB0_cblen_lun_flag >> 24) & 0xFF) + ((ptcbw->CB1_CB15[0]&0xFFFFFF)<<8);
CDB[1] = ((ptcbw->CB1_CB15[0] >> 24) & 0xFF) + ((ptcbw->CB1_CB15[1]&0xFFFFFF)<<8);
CDB[2] = ((ptcbw->CB1_CB15[1] >> 24) & 0xFF) + ((ptcbw->CB1_CB15[2]&0xFFFFFF)<<8);
CDB[3] = ((ptcbw->CB1_CB15[2] >> 24) & 0xFF) + ((ptcbw->CB1_CB15[3]&0xFFFFFF)<<8);
// Parse SCSI command
if (!(((CDB[0]&0xFF) == SCSI_OP_SET0)||((CDB[0]&0xFF) == SCSI_OP_SET1)||((CDB[0]&0xFF) == SCSI_OP_SET2)))
return -1;
// check sum
if(calc_sum_v2(CDB[0],CDB[1],CDB[2],CDB[3])) {
tCSW.u8Status = CSW_STATUS_CMD_FAIL;
u32Usb_buffer[0] = 0;
#ifdef USBROM_RTOS_DBG
DBG_DUMP("CHKSUM FAILED\r\n");
#endif
return -1;
}
tCSW.u8Status = CSW_STATUS_CMD_PASS;
switch (((CDB[0] >> 8) &0xFF)) {
case SCSIOP_OUT_OPEN_DEVICE: {
nvtdev_opened = 1;
#ifdef USBROM_RTOS_DBG
DBG_DUMP("SCSIOP_OUT_OPEN_DEVICE\r\n");
#endif
}
break;
case SCSIOP_IN_WAIT_DONE: {
usbrom_exit = 1;
#ifdef USBROM_RTOS_DBG
DBG_DUMP("SCSIOP_IN_WAIT_DONE\r\n");
#endif
}
break;
case SCSIOP_IN_IS_NVT: {
tSCSIDeviceResp.u8Flags = CBW_FLAG_IN;
tSCSIDeviceResp.u8MemIndex = CARD_INDEX_SRAM;
tSCSIDeviceResp.u16DataResidue = 4;
tCSW.u8Status = CSW_STATUS_CMD_PASS;
u32Usb_buffer[0] = 0x70210000;
#ifdef USBROM_RTOS_DBG
DBG_DUMP("SCSIOP_IN_IS_NVT\r\n");
#endif
}
break;
case SCSIOP_OUT_ADDR_WRITE: {
if(nvtdev_opened == 0) {
tCSW.u8Status = CSW_STATUS_CMD_FAIL;
} else {
// address
temp1 = ((CDB[0]>>16)&0xFFFF)+((CDB[1]&0xFFFF)<<16);//u8to32(&ptcbw->u8CB[2]);
// data
temp2 = ((CDB[1]>>16)&0xFFFF)+((CDB[2]&0xFFFF)<<16);//u8to32(&ptcbw->u8CB[6]);
*(INT32U *)temp1 = temp2;
__asm__ __volatile__("dsb\n\t");
#ifdef USBROM_RTOS_DBG
DBG_DUMP("SCSIOP_OUT_ADDR_WRITE 0x%08X 0x%08X\r\n", temp1, temp2);
#endif
}
}
break;
case SCSIOP_IN_ADDR_READ: {
if(nvtdev_opened == 0) {
tCSW.u8Status = CSW_STATUS_CMD_FAIL;
} else {
// address
temp1 = ((CDB[0]>>16)&0xFFFF)+((CDB[1]&0xFFFF)<<16);//u8to32(&ptcbw->u8CB[2]);
tSCSIDeviceResp.u8Flags = CBW_FLAG_IN;
tSCSIDeviceResp.u8MemIndex = CARD_INDEX_SRAM;
tSCSIDeviceResp.u16DataResidue = 8;
u32Usb_buffer[0] = temp1;
u32Usb_buffer[1] = *((INT32U *)temp1);
#ifdef USBROM_RTOS_DBG
DBG_DUMP("SCSIOP_IN_ADDR_READ 0x%08X 0x%08X\r\n", temp1, u32Usb_buffer[1]);
#endif
}
}
break;
#if 0 //only rom code support
case SCSIOP_OUT_WRLOADER: {
if(nvtdev_opened == 0) {
tCSW.u8Status = CSW_STATUS_CMD_FAIL;
} else {
// address
temp1 = ((CDB[0]>>16)&0xFFFF)+((CDB[1]&0xFFFF)<<16);//u8to32(&ptcbw->u8CB[2]);
tSCSIDeviceResp.u32IOAddr = temp1;
tSCSIDeviceResp.u8Flags = CBW_FLAG_OUT;
tSCSIDeviceResp.u8MemIndex = CARD_INDEX_FSM_SS;
tSCSIDeviceResp.u16DataResidue = ptcbw->u32DataTransferLength;
#ifdef USBROM_RTOS_DBG
DBG_DUMP("SCSIOP_OUT_WRLOADER 0x%08X 0x%08X\r\n", temp1, tSCSIDeviceResp.u16DataResidue);
#endif
}
}
break;
#endif
default: {
if(nvtdev_opened == 0) {
tCSW.u8Status = CSW_STATUS_CMD_FAIL;
} else {
int ret = -1;
unsigned int OutDataBuf=0, insize=0;
if (guiU2MsdcCheck_cb != NULL) {
ret = guiU2MsdcCheck_cb((unsigned int)ptcbw, (unsigned int *) &OutDataBuf, (unsigned int *)&insize);
} else {
ret = -1;
}
if(ret == 0) {
if (ptcbw->CB0_cblen_lun_flag & CBW_FLAG_IN) {
tSCSIDeviceResp.u32IOAddr = OutDataBuf;
tSCSIDeviceResp.u8Flags = CBW_FLAG_IN;
tSCSIDeviceResp.u8MemIndex = CARD_INDEX_FSM_SS;
tSCSIDeviceResp.u16DataResidue = insize;
} else {
tSCSIDeviceResp.u32IOAddr = OutDataBuf;
tSCSIDeviceResp.u8Flags = CBW_FLAG_OUT;
tSCSIDeviceResp.u8MemIndex = CARD_INDEX_FSM_SS;
tSCSIDeviceResp.u16DataResidue = ptcbw->u32DataTransferLength;
}
trigger_done_cb = 1;
} else {
return ret;
}
}
}
break;
}
return 0;
}
_THUMB2 void fLib_USB_Update_FW(void)
{
debug_msg("USBFW UPDATE\r\n");
vUsbInit();
while (1) {
vUsbIsr2();
if(usbrom_exit > 1) {
//mdelay(300); //make sure that pc recevie scsi status
timer_delay(300000);
vUsbUnplug();
timer_delay(300000);
//mdelay(300); //make sure that pc recevie usb plug-out single
break;
}
}
usbrom_exit = 0;
}