⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mscbot.c

📁 <B>SMSC USB2.0 Flash硬盘驱动源码</B>
💻 C
📖 第 1 页 / 共 3 页
字号:
/*============================================================================
  ____________________________________________________________________________
                                ______________________________________________
   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 + -