www.pudn.com > SMSC USB2.0.zip > fmcapp.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. 
  ____________________________________________________________________________ 
  ____________________________________________________________________________ 
  fmcapp.c - the application interface manager and main application thread. 
  ____________________________________________________________________________ 
  comments tbd 
  ____________________________________________________________________________ 
  Revision History 
  Date      Who  Comment 
  ________  ___  _____________________________________________________________ 
  09/14/01  cds  moved from atapi.c to help isolate the stages.  this abstraction 
                 could cost some performance, however. 
           
  05/31/00  tbh  initial version 
============================================================================*/ 
/////////////////////////////////////////////////////////////////////////////// 
// 
// USER INTERFACE MODULE 
// 
// mass storage, bulk only, atapi 
// 
//////////////////////////////////////////////////////////////////////////////// 
#include "fmc.h" 
 
 
 
// ----------------------------------------------------------------------------- 
// Begin Source    
// ----------------------------------------------------------------------------- 
 
//------------------------------------------------------------------------------ 
// special smsc hardware debug registers  
//------------------------------------------------------------------------------ 
 
 
bit     g_device_present ; 
bit     g_poll_for_drq ; 
bit     g_use_dma ;  
bit     g_disable_iordy ;  
bit     g_data_direction ; /* 1 = k_data_in, 0 = k_data_out */ 
bit     g_prevent_reset ;  /* 1=k_true, 0=k_false.  Don't keep resetting the device during enumeration */ 
bit     g_device_present ; /* 1=k_true, 0=k_false.  This doesn't mean the device is an ATAPI device! */ 
bit     g_forced_phase_error; 
bit     g_tx_missed_ack; 
bit     g_doing_dma ; 
 
 
// device type 
#define k_device_type_ata    0 
#define k_device_type_atapi  1 
#define k_device_type_floppy 2 
 
// ata device characteristics 
uint8   g_dev_max_dma_mode ; /* represents max DMA mode supported by the device */ 
 
 
 
 
//------------------------------------------------------------------------------ 
// global variables - these can be cleaned up, and probably placed into 
// our x_data buffer, freeing up ram for some other optimization 
//------------------------------------------------------------------------------ 
uint8   g_ix_ata_thread; 
uint32  g_original_request_length ;  
 
// pio DRQ-block transfer variables 
uint32  g_remaining_drq_length ; 
uint16  g_available_pkt_length ;  
uint16  g_available_pkt ; // offset of next available byte.  k_data_in: next free, k_data_out: next valid  
uint8   g_available_buffer ;     // start sending to host on.... 0 = A , 1 = B 
uint8   g_last_packet ; 
 
 
uint16      g_ata_data_xfer_length ; /* Data Transfer Length for use ONLY with the Ata state machine */ 
 
 
 
 
static void   fmcapp_cfc_init_done() reentrant ; 
 
//------------------------------------------------------------------------------ 
// <<< ATA INTERFACE - MANAGER >>> 
// Target MCU:  
//  200 
// Declaration:  
//  uint8 ata_mngr(t_message *msgp); 
// Purpose:  
//  This is the manager for all things related to the ata interface. 
// Arguments:  
//  None. 
// 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. 
//------------------------------------------------------------------------------ 
uint8 fmcapp_mngr(t_message *msgp) reentrant  
{ 
    uint8 i ; 
 
    TRACE1(328, fmc, 0, "+fmcapp_mngr() msg_id:%d", message_rd_id(msgp)); 
    switch(message_rd_id(msgp)) 
    { 
    //-------------------------------------------------------------------------- 
    // always return k_success for these. 
    //-------------------------------------------------------------------------- 
    case k_msg_initialize: 
        TRACE0(329, fmcapp, 1, "k_msg_initialize"); 
       
#ifdef TRACE 
        // print out compile-time options  
        fmcapp_trace_compiled_opts() ;  
#endif  
        // create thread 
        g_ix_ata_thread = thread_create(fmcapp_create_thread, NULL, k_true); 
 
        // register endpoints - do nothing here as only the default control pipe is used 
        ctl_bind_endpoint(2, g_ix_ata_thread, NULL);   
        ctl_bind_endpoint(2, g_ix_ata_thread, NULL); 
       
        // register interfaces - must jive with the configuration descriptor... 
        ctl_bind_interface(0, fmcapp_cpex); 
       
        // set up the gpio interface 
        gpio_initialize(); 
       
        // application initializations  
        for(i=0;i>> 
// Target MCU:  
//  200 
// Declaration:  
//  uint8 ata_cpex(t_message *msgp); 
// Purpose:  
//  Handles requests targeted to its interface: standard, class, vendor. 
// Arguments:  
//  None. 
// 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. 
//------------------------------------------------------------------------------ 
uint8 fmcapp_cpex(t_message *msgp) reentrant 
{ 
    uint8 pktsz; 
    uint8 pnr_loc; 
    t_usb_rqst *rqstp; 
    rqstp = (t_usb_rqst *)(message_rd_arg(msgp)); 
    switch(message_rd_id(msgp)) 
    { 
    // standard requests 
    //-------------------------------------------------------------------------- 
    // Note - the 97C2xx has an SIE that is smart enough to handle most standard 
    // control requests.  therefore, many of these messages won't appear in this cpex 
    // as they would if this were built for the 100 or 102 mcu's 
     
       
      // class specific requests 
      //-------------------------------------------------------------------------- 
    case k_cls_mass_storage_reset:         
        trace0(0, atapi, 0, "got k_hci_msc_reset"); 
         
        // command block reset 
        // $$$ cds to do - we MUST find a way to NAK the host until  
        // the reset has occured by order of the Mass Storage Class Spec 
        // fmc_soft_reset()... 
 
        // for now, just send a usbreset and return success... it'll work, but it's technically 
        // non compliant for devices that actually send this message 
        thread_set_sync(g_ix_ata_thread, kbm_sync_usbrst) ; 
        return k_success; 
 
    case k_cls_mass_storage_get_max_lun:         
        trace0(0, atapi, 0, "got k_dci_msc_get_max_lun"); 
         
        g_tmp = 0; 
        // tell the data pump where to find it and how much there is  
        _payload_source(&g_tmp, k_lun_max); 
        return k_success; 
         
        // os messages 
    case k_msg_source_payload:   
        // load some application specific data into a packet buffer 
        // return k_in_progress if app expects to be supply at least one more packet's worth of data 
        // return k_finished otherwise 
        pnr_loc = *(uint8 *)(message_rd_arg(msgp)); 
        pktsz = _min(g_data_len, k_maxpktsz); 
        g_data_len -= pktsz; 
        mmu_wr_pkt(0, pnr_loc, g_source_addr, pktsz); 
        g_source_addr += pktsz; 
#ifdef k_mcu_97200 
        x_ep0tx_bc = pktsz; 
#endif 
        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_loc = *(uint8 *)(message_rd_arg(msgp)); 
#ifdef k_mcu_97200 
        pktsz = x_ep0rx_bc; 
#else 
        pktsz = _min(g_data_len, k_maxpktsz); 
#endif 
        g_data_len -= pktsz; 
        mmu_rd_pkt(pnr_loc, pktsz, g_sink_addr); 
        g_sink_addr += pktsz; 
        return g_data_len ? k_in_progress : k_finished; 
    default:  
        return k_error; 
    } 
    return k_error; 
} 
//------------------------------------------------------------------------------ 
// <<< ATA INTERFACE - POLLER >>> 
// Target MCU:  
//  200 
// Declaration:  
//  void ctl_poll(void); 
// Purpose:  
//  Poll for non-interrupt events related to this interface and synchronize  
//  the associated thread(s). 
// Arguments:  
//  None. 
// Return:  
//  None. 
// 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 flounder, panic, flail, and eventually expire. 
//------------------------------------------------------------------------------ 
// i think we may need this... 
// implement ata_poll_whatever() here if you end up needing it... 
//------------------------------------------------------------------------------ 
// <<< ATA INTERFACEE - THREAD >>> 
// Target MCU:  
//  200 
// Purpose:  
//  Handles the application specific peripheral control state machine for this  
//  interface. 
//------------------------------------------------------------------------------ 
 
/*****************************************************************************/ 
/* ATAPI_CreateThread aka wait_until_atapi_thread_gets_created()             */ 
/*****************************************************************************/ 
void fmcapp_init_2() reentrant ; 
void fmcapp_init_3() reentrant ; 
void fmcapp_init_4() reentrant ; 
void fmcapp_create_thread() reentrant 
{ 
    TRACE0(332, fmcapp, 0, "+fmcapp_create_thread()") ; 
     
 
    // initialize fmcapp state variables 
    g_available_pkt_length = 0x0000; 
     
 
 
 
#if defined(k_mcu_97200) || defined(k_mcu_97201) 
    // frob the fmc registers to prepare the fmc hardware.  
    // clr muxen to select ATA interface. 
 
    x_ata_ctl |= kbm_ata_ctl_out_control ; 
    x_ata_ctl &= ~kbm_ata_ctl_muxen ;  
 
#endif 
 
#if defined(k_mcu_97210) 
 
    // initialize the compact flash controller & device 
    thread_run_dfa(fmc_init, NULL, fmcapp_init_2) ; 
 
#endif 
} 
 
 
 
 
 
 
 
 
//------------------------------------------------------------------------------ 
void  fmcapp_trace_compiled_opts() reentrant  
{ 
 
    TRACE0(335, fmcapp, 0, "** SMSC Flash Media Controller Configuration **") ; 
    TRACE4(336, fmcapp, 0, "  -firmware version:  %d.%d.%d.%d", kbcd_dev_version_major, kbcd_dev_version_minor, kbcd_dev_version_external_change, kbcd_dev_version_internal_change) ;  
 
    TRACE1(337, fmcapp, 0, "  -dma support:      %c", k_dma_mode > 0 ? 'Y' : 'N' ) ; 
 
    if(k_dma_mode > 0) 
    { 
        switch(k_dma_mode) 
        { 
        case k_dma_mode_multiword_0 :  
            trace0(0, atapi, 0, "DMA Mode: Multiword Mode 0") ; 
            break; 
        case k_dma_mode_multiword_1 : 
            trace0(0, atapi, 0, "DMA Mode: Multiword Mode 1") ; 
            break; 
        case k_dma_mode_multiword_2 : 
            trace0(0, atapi, 0, "DMA Mode: Multiword Mode 2") ; 
            break; 
        case k_dma_mode_ultra_dma_0 : 
            trace0(0, atapi, 0, "DMA Mode: Ultra DMA Mode 0") ; 
            break; 
        case k_dma_mode_ultra_dma_1 : 
            trace0(0, atapi, 0, "DMA Mode: Ultra DMA Mode 1") ; 
            break; 
        case k_dma_mode_ultra_dma_2 : 
            trace0(0, atapi, 0, "DMA Mode: Ultra DMA Mode 2") ; 
            break;  
        case k_dma_mode_ultra_dma_3 : 
            trace0(0, atapi, 0, "DMA Mode: Ultra DMA Mode 3") ; 
            break;  
        case k_dma_mode_ultra_dma_4 : 
            trace0(0, atapi, 0, "DMA Mode: Ultra DMA Mode 4") ; 
            break;  
        case k_dma_mode_ultra_dma_5 : 
            trace0(0, atapi, 0, "DMA Mode: Ultra DMA Mode 5") ; 
            break;  
 
 
        default: 
            trace1(0, atapi, 0, "DMA Mode:  Unknown Mode Specifed (%d)", k_dma_mode) ; 
            break;  
        } 
        trace1(0, atapi, 0, "DMA Used for Data In (ATA to SIE): %c",  (k_dma_data_in ? 'Y' : 'N') ) ; 
        trace1(0, atapi, 0, "DMA Used for Data Out (SIE to ATA): %c", (k_dma_data_out ? 'Y' : 'N') ) ; 
    } 
 
#ifdef SHADOW_PIO_COMPLETE 
    TRACE0(338, fmcdev, 0, "Shadow PIO_COMPLETE: Y") ; 
#else 
    TRACE0(339, fmcdev, 0, "Shadow PIO_COMPLETE: N") ; 
#endif 
 
#ifdef k_support_ata 
    TRACE0(340, fmcdev, 0, "ATA Device Support:Y") ; 
#else 
    TRACE0(341, fmcdev, 0, "ATA Device Support:N") ; 
#endif 
 
}