📄 mscbot.c
字号:
/*============================================================================
____________________________________________________________________________
______________________________________________
SSSS M M CCCC Standard Microsystems Corporation
S MM MM SSSS C Austin Design Center
SSS M M M S C 11000 N. Mopac Expressway
S M M SSS C Stonelake Bldg. 6, Suite 500
SSSS M M S CCCC Austin, Texas 78759
SSSS ______________________________________________
____________________________________________________________________________
Copyright(C) 1999, Standard Microsystems Corporation
All Rights Reserved.
This program code listing is proprietary to SMSC and may not be copied,
distributed, or used without a license to do so. Such license may have
Limited or Restricted Rights. Please refer to the license for further
clarification.
____________________________________________________________________________
Notice: The program contained in this listing is a proprietary trade
secret of SMSC, Hauppauge, New York, and is copyrighted
under the United States Copyright Act of 1976 as an unpublished work,
pursuant to Section 104 and Section 408 of Title XVII of the United
States code. Unauthorized copying, adaption, distribution, use, or
display is prohibited by this law.
____________________________________________________________________________
Use, duplication, or disclosure by the Government is subject to
restrictions as set forth in subparagraph(c)(1)(ii) of the Rights
in Technical Data and Computer Software clause at DFARS 52.227-7013.
Contractor/Manufacturer is Standard Microsystems Corporation,
80 Arkay Drive, Hauppauge, New York, 1178-8847.
____________________________________________________________________________
____________________________________________________________________________
mscbot.c - mass storage class bulk only transport
____________________________________________________________________________
comments tbd
____________________________________________________________________________
Revision History
Date Who Comment
________ ___ _____________________________________________________________
01/15/01 tbh initial version
03/17/01 tbh upgraded to use MinimOS-2.1
07/27/01 tbh modulatized during port to '201 (was usbdp.c, now split apart)
09/20/01 tbh made use of new sir_rd_configuration() port to 20x allowing
elimination of some #ifdefs
09/##/01 tbh optimized for speed
11/27/01 cds enabled the data mux for the lun after validating CBW but
before processing the cb.
12/04/01 tbh check lun media flags after sending ststus to see if need
to get out back to dev thread to re-establish the media.
02/26/02 tbh added logical to physical lun mapping
03/11/02 tbh added bit g_force_card_establish. on error on current card
clear devce type to none so card wil be reset/initialized.
03/25/02 DS Sometimes after we set the bit to stall the RX Pipe, we still get an outnak before
the stall is realized. This is filtered out in mscbot_wait_status_end().
04/01/02 tbh adjusted the leds to indicate the phy lun, sd and mmc combined
06/10/02 tbh rewrote it as high priority thread (chained isr's) instead of
foreground thread to reduce cbw/csw processing overhead.
06/20/02 tbh only stall the rx pipe if there was an error AND there is residue
AND the residue is more than 512 bytes. this prevents seeing
a stall on the next cbw.
06/21/02 ds Windows 2000 has been noted to reset the device if a stall is issued on a successful read
with a residue. So, changed it to issue a stall only on a failure.
06/24/02 tbh tweaked code for k_pfm_led to get the SD activity light correct.
06/28/02 tbh/ds added _stall_ndp2_rx flag to know if writes need to be stalled
since the presence of residue is insufficient to decide.
_endpoint_unmask_in/outnak was broken. it did not clear the
correct interrupt bit. it is fixed (knock on wood).
07/10/02 tbh modified cpex to handle dfu requests
07/18/02 tbh don't diddle leds in fgnd_hpbot_wait_create.
also, no longed uses or manipulates g_active_lun, nor does it
touch the fmc mux. (it uses a new local _active_lun).
07/23/02 baw increased the maximum allowed length of the cdb to 16,
because password commands require 16 bytes
07/30/02 ds Moved _endpoint_unmask_innak(k_rx_pipe) macro to mscbot.h so that sd.c can access it.
08/07/02 tbh added _endpoint_unmask_outnak(k_rx_pipe) to be resume handler
to ensure hearing outnak after suspend
09/06/02 ds Implemented the 'custom' blinking light for data access, which is controlled from the
high priority fns of data access. Refer the header for device.c for a detailed explanation
09/07/02 tbh renames some globals to have meaningful names
09/20/02 tbh modified activility led actions to use new functions.
09/22/02 tbh eliminated unused code on 242 builds (dfu optional)
09/26/02 cds added mscbot_tx_data_buffer() function to send simple small
data buffers as data-phase response for commands... the function
has some 32-bit calculations and minimos calls that make it
somewhat code-heavy, and having this central location results
in approximately 1K of code savings...
09/30/02 ds Fixed the bug where the activity led goes to its idle state on suspend. This caused
it to stay on if the idle state is to be ON. Changes to code:
-Removed the call to dev_turn_off_activity_indicator from fgnd_hpbot_wait_create()
10/01/02 ds Added a new funciton mscbot_rx_data_buffer to receive data on bulk pipe.
10/02/02 ds Modified mscbot_rx_data_buffer so that we will wait for the data packet and return a timeout error
on an error condition.
10/02/02 ds buffer_rx_enable should be a macro.Rolling back to previous form of code.
10/02/02 ds fixed mscbot_rx_data_buffer to strictly receive data on buffer B
10/02/02 cds moved g_bot_cbw into xdata to regain data/stack space to prevent
stack overflows on hierarchy-heavy media protocols.
============================================================================*/
#include "project.h"
#include "dev.h"
//------------------------------------------------------------------------------
// exported globals
xdata t_cbw g_bot_cbw; // command block wrapper
t_udw32 g_bot_data_len; // number of bytes to transfer
t_xfer_dir g_bot_xfer_dir; // k_dir_read or k_dir_write
//------------------------------------------------------------------------------
// private
static uint8 _active_lun; // the lun for the current cbw/csw
static uint8 _status; // mscbot transfer status
static bit _tx_missed_ack; // if true must rexmit previous csw
static bit _ndp2_rx_stalled; // can't read register bit since fw doesnt process clear stall
// and it could happed before we check the stall bit in ep2ctl.
static bit _stall_ndp2_rx; // set in wait_status_start on an outnak
static bit _data_access = k_false; //flag to tell if it is a data access cmd... there is a better way, but
//but I am in a hurry
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
#define _endpoint_unmask_outnak(k_rx_pipe); \
{ \
_mcu_register_wr(x_isr_nak, 1 << (2 * k_rx_pipe)); \
_mcu_register_clrbit(x_imr_nak, 2 * k_rx_pipe); \
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
#define _endpoint_tx_enable(k_tx_pipe); \
{ \
_mcu_register_set_bits(x_ep2_ctl, kbm_ep2_ctl_dir); \
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
#define _endpoint_rx_enable(k_rx_pipe); \
{ \
_mcu_register_clr_bits(x_ep2_ctl, kbm_ep2_ctl_dir); \
_mcu_register_set_bits(x_isr0, kbm_isr0_ramwr_a |kbm_isr0_ramwr_b); \
_mcu_register_clr_bits(x_imr0, kbm_isr0_ramwr_a |kbm_isr0_ramwr_b); \
g_endpoint[2].rxpnr = 0; \
}
//------------------------------------------------------------------------------
// Declaration:
// t_result mscbot_mngr(t_message_ref msgp);
//
// Purpose:
// This is the manager for all things related to the mscbot interface.
//
// Arguments:
// msgp - a reference to a message
//
// Return:
// k_success
// K-error
//
// Note:
// Do NOT yield from this routine. It is NOT part of any thread. It does
// not execute in an any thread's context. Yielding from within this function
// will cause your firmware to crash.
//
// Since:
// atapi-2.0
//------------------------------------------------------------------------------
t_result mscbot_mngr(t_message_ref msgp) reentrant
{
trace0(0, bot, 0, "mscbot_mngr()");
switch (message_rd_id(msgp))
{
//--------------------------------------------------------------------------
// always return k_success for these.
//--------------------------------------------------------------------------
case k_msg_initialize:
trace0(0, bot, 0, "k_msg_initialize");
// create threads - mscbot could run on its own thread, but in this case
// its being run on the device thread.
//g_ix_mscbot_thread = thread_create(mscbot_thread_wait_create, NULL, k_yes);
// register endpoints - do nothing here as only the default control pipe is used
ctl_bind_endpoint(1, g_ix_dev_thread, ctl_cpex); // unused interrupt pipe...
ctl_bind_endpoint(k_tx_pipe, g_ix_dev_thread, ctl_cpex);
// register interfaces - must jive with the configuration descriptor...
ctl_bind_interface(0, mscbot_cpex);
// init the isr hooks $$$.
_isr_bind_abort_sync(kbm_sync_abort);
_isr_bind_dma_owner(0, kbm_sync_none);
return (k_success);
case k_msg_usbrst:
trace0(0, bot, 0, "k_msg_usbrst");
return (k_success);
case k_msg_resume:
trace0(0, bot, 0, "k_msg_resume");
// 08/07/02 tbh added this line to be sure to hear outnak after suspend
_endpoint_unmask_outnak(k_rx_pipe);
return (k_success);
case k_msg_suspend:
trace0(0, bot, 0, "k_msg_suspend");
// put the pipe into the tx direction so it will nak any cbw's until
// after the set-config is processed by the udc core AND it is noticed and
// processed by the foreground. msc_bot_wait_pipe_ready_for_rx()
// will keep waking on outnaks and re-arming itself if the set-config
// has not been fully processed.
// this prevents on resume receiving a cbw before processing set-config
// thus sending the drive a command before it is powered on.
_endpoint_tx_enable(k_tx_pipe);
return (k_success);
}
// unexpected message
trace0(0, bot, 0, "error");
return (k_error);
}
//------------------------------------------------------------------------------
// Declaration:
// t_result mscbot_cpex(t_message_ref msgp);
//
// Purpose:
// Handles requests targeted to its interface: standard, class, vendor.
//
// Arguments:
// msgp - a reference to a message
//
// Return:
// k_success - Causes the protocol engine to complete the status stage successfully.
// k_error - Causes the protocol engine to stall the control pipe.
// k_in_progress - For k_msg_source_payload, causes the protocol engine to deliver
// another empty packet buffer to the cpex to be loaded for transmission.
// For k_msg_sink_payload, informs the protocol engine that the cpex expects at
// least one more payload buffer to be delivered to it by the protocol engine.
// k_finished - For k_msg_source_payload and k_msg_sink_payload, informs the
// protocol engine that the data phase is complete and no more data is expected
// in either direction.
//
// Note:
// Do NOT yield from this routine. It is part of the protocol engine's thread.
// It executes in the context of g_ix_ctl_thread. Yielding from within this
// function will cause the protocol engine's state machine to float belly up.
// And that will cause your firmware to shuffle off this mortal coil, post haste.
//
// Since:
// atapi-2.0
//------------------------------------------------------------------------------
t_result mscbot_cpex(t_message_ref msgp) reentrant
{
uint8 pktsz;
uint8 pnr;
t_usb_rqst *rqstp;
rqstp = (t_usb_rqst *)message_rd_arg(msgp);
switch (message_rd_id(msgp))
{
// standard requests
case k_dsi_usb_get_status:
trace0(0, nil, 0, "RQ_GET_STATUS: interface");
// interface status is always 0 per usb spec
g_wtmp = 0;
// tell the data pump where to find it and how much there is
_payload_source(&g_wtmp, 2);
return (k_success);
case k_hsi_usb_clr_feature:
trace0(0, nil, 0, "RQ_CLEAR_FEATURE: interface?");
// this is always an error per the usb spec
return (k_error);
case k_hsi_usb_set_feature:
trace0(0, nil, 0, "RQ_SET_FEATURE: interface?");
// this is always an error per the usb spec
return (k_error);
case k_dsi_usb_get_interface:
trace0(0, nil, 0, "RQ_GET_INTERFACE");
// this interface has no alternate settings
g_tmp = 0;
// tell the data pump where to find it and how much there is
_payload_source(&g_tmp, 1);
return (k_success);
case k_hsi_usb_set_interface:
trace0(0, bot, 0, "RQ_SET_INTERFACE");
// this interface has no alternate settings, only 0 as a selection
if (rqstp->wValueLo)
return (k_error);
return (k_success);
// class specific requests
case k_hci_mscbot_reset:
// perform the class specific soft reset
trace0(0, bot, 0, "RQ k_hci_mscbot_reset");
return (k_success);
case k_hci_mscbot_getmaxlun:
trace0(0, bot, 0, "RQ k_hci_mscbot_getmaxlun");
g_tmp = k_max_log_lun-1;
trace1(0, bot, 0, " maxlun:%d)", g_tmp);
// tell the data pump where to find it and how much there is
_payload_source(&g_tmp, 1);
return (k_success);
#ifdef k_opt_dfu
// dfu class specific message - must be intercepted here has a hack
// since the chip only has one physical interface so there cannot be
// a dangling dfu interface
case k_hci_dfu_detach:
trace0(0, dfu, 0, "mscbot_cpex intercepting: k_hci_dfu_detach");
return (dfu_cpex(msgp));
#endif
#ifdef k_opt_dfu
case k_msg_transaction_done:
trace0(0, dfu, 0, "mscbot_cpex routing k_msg_transaction_done to dfu_cpex");
return (dfu_cpex(msgp));
#endif
// os messages
case k_msg_source_payload:
// load some application specific data into a packet buffer
// return k_in_progress if app expects to supply at least one more packet's worth of data
// return k_finished otherwise
pnr = *(uint8 *)message_rd_arg(msgp);
pktsz = _min(g_data_len, k_maxpktsz);
g_data_len -= pktsz;
mmu_wr_pkt(0, pnr, g_source_addr, pktsz);
g_source_addr += pktsz;
return (g_data_len ? k_in_progress : k_finished);
case k_msg_sink_payload:
// unload data from a packet buffer and do something application specific with it
// return k_in_progress if app can process this request
// return k_finished otherwise
pnr = *(uint8 *)message_rd_arg(msgp);
pktsz = _min(g_data_len, k_maxpktsz);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -