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

📄 ata.c

📁 u盘MCU端源代码,开发U盘的可以参考.
💻 C
📖 第 1 页 / 共 5 页
字号:
/*============================================================================
  ____________________________________________________________________________
                                ______________________________________________
   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.
  ____________________________________________________________________________
  ____________________________________________________________________________
  <module name> - <module description>
  ____________________________________________________________________________
  comments tbd
  ____________________________________________________________________________
  Revision History
  Date      Who  Comment
  ________  ___  _____________________________________________________________
  04/20/01  cds  initial version
  09/##/01  tbh  optimized for speed
  11/16/01  cds  - updated code to use lun instance data instead of globals.
                 - tried global search & replace of thread_clr_sync to
                   _thread_clr_sync but it turns out the bug is more devious
                   and is attached to bits_got, not the thread_clr_sync.
  11/26/01  cds  modified ata_pio_rd to include blk-xfer for 210 instead of
                 calling pio_wr_pkt.  Tests whether high-speed or full-speed
                 and only sets 512-byte-pkts for blk-xfer in hs connections.
  11/28/01  rcc  modified ata_pio_rd Tests whether high-speed or full-speed
                 and only sets 512-byte-pkts for blk-xfer in hs connections also
                 CLEARS this bit if FS and does this before the blk-xfer bit it set.
  12/04/01  tbh  tweaked identify_device for newish fmc style _lun_data access.
  12/13/01  tbh  tweaked data xfers to use fmc_transfer()
  02/26/02  tbh  added NULL placeholder in _fmc_set_callback() invocations
  03/12/02  tbh  minor renaming to fit the fmc project's idiom
  04/15/02  tbh  ensure fmc_options set to 0 before read/write
  05/20/02  tbh  turn off multiple emulation in ata_read_end_xfer.
                 added ata_write_end_xfer to ensure multiple emulation turned off
                 in case of aborted transfer.
  06/05/02  cds  added trace statement to dump the # of sectors per irq (burst)
                 of the read/write multiple command from identify device data
  06/10/02  tbh  performance enhancements using _ata_register_wr() macro to replace
                 ata_register_wr() function.  other minor enhancements.
  06/20/02  tbh  in ata_initialize_media2 set the CF into pio mode 4 (from default 0)
  06/25/02  tbh  subtract 1 from lba_max to get correct capacity reported to host
                 to fix the problem with quick format.
  07/09/02  cds  replaced _work_buf with common g_sector_buffer, as used in
                 sm, ms, and nand luns.
  07/23/02  cds  added obsolete PIO Transfer Cycle Mode field (word 51) to
                 identify device data.  Moved the setting of the cfc_ata_mode_ctl
                 register into the identify device function so that as soon as
                 the mode is determined, the register is set, but before then,
                 PIO mode 0 is used (to obtain the ID data).
  08/29/02  tbh  added rudimentary profiling of ata drives (to identify the
                 edata 32mb cf card and drop it to mode 0)
  09/10/02  tbh  forced reporting as removable media always because some CF
                 cards seem to say they are fixed disks.
  10/17/02  cds  - project-wide lun data & vtbl paging to reduce code space.
                 - removed g_active_media from _lun_data, _lun_() virtual functions
                 - added _lun_data_rd() and _lun_data_wr() macros to bypass lun paging
                 - added lun_set_active(log_lun) function to switch luns
                                  
============================================================================*/
#define __ata_dot_c__
#include "project.h"
#include "dev.h"

code _vtbl_defn(ata);

#ifdef k_flash_family
#define k_lun_ata k_lun_cf
#else
#define k_lun_ata 0
#endif

// to use this optimization you want fmc_select_cf() to set CKCON = 0x00 also...
#define _ata_clock_slow() CKCON=0x02
#define _ata_clock_fast() CKCON=0x00

//------------------------------------------------------------------------------
// exported globals
xdata uint8   g_dev_max_dma_mode;  // represents max DMA mode supported by the device

// ata device characteristics
bit           g_use_dma;
bit           g_disable_iordy;
xdata uint8   g_dma_mode_current;

// ata device capabilities & properties
// these are all relevant properties from ata identify device data.
xdata uint16  g_ata_dev_cmdset_support_1;
xdata uint16  g_ata_dev_cmdset_support_2;
xdata uint16  g_ata_dev_cmdset_support_3;
xdata uint16  g_ata_dev_cmdset_enabled_1;
xdata uint16  g_ata_dev_cmdset_enabled_2;
xdata uint16  g_ata_dev_cmdset_enabled_3;
xdata uint16  g_ata_dev_num_log_cyl;
xdata uint16  g_ata_dev_num_log_hds;
xdata uint16  g_ata_dev_num_log_sec_per_trk;
xdata uint16  g_ata_dev_caps_1;
xdata uint16  g_ata_dev_caps_2;

//+-----------------------------------------------------------------------------
// Name:
//   ata_dump_build_options
//
// Declaration:
//   void ata_dump_build_options(void);
//
// Purpose:
//   Debugging.  Dumps the build options.
//
// Arguments:
//   None.
//
// Return:
//   None.
//
// Notes:
//   None.
//
// Since:
//   fmc-1.0
//------------------------------------------------------------------------------
void ata_dump_build_options(void) reentrant;
void ata_dump_build_options() reentrant
{
  trace0(0, ata, 0, "ata_dump_build_options()");
  trace1(0, ata, 0, "dma mode: %02x", k_dma_mode);
  trace0(0, ata, 0, "Shadow PIO_COMPLETE: Y");
  trace0(0, ata, 0, "ATA Device Support:Y");
}

//+-----------------------------------------------------------------------------
// Name:
//   ata_register_wr
//
// Declaration:
//   void ata_register_wr(t_ata_register_ref r, uint8 d);
//
// Purpose:
//   Write a value to an ata register.
//
// Arguments:
//   r - the t_ata_register_ref identifying the register to be written.
//   d - the uint8 to be written there.
//
// Return:
//   None.
//
// Notes:
//   None.
//
// Since:
//   fmc-1.0
//------------------------------------------------------------------------------
void ata_register_wr(t_ata_register_ref r, uint8 d) reentrant
{
  _ata_clock_slow();
  trace2(0, ata, 0, "ata_register_wr(%04x=%02x)", (uint16)r, d);
  while( !(x_cfc_stat & kbm_cfc_stat_xrdy));  // <-- WARNING! WARNING! DANGER, WILL ROBINSON!
  *r = d;
  _ata_clock_fast();
}

//------------------------------------------------------------------------------
// performance enhancement is to use a macro in ata_read/write_begin_burst
// while issuing the command
//------------------------------------------------------------------------------
#define _ata_register_wr(__r, __d)            \
{                                             \
  _ata_clock_slow();                          \
  while( !(x_cfc_stat & kbm_cfc_stat_xrdy));  \
  *(__r) = (__d);                             \
  _ata_clock_fast();                          \
}

//+-----------------------------------------------------------------------------
// Name:
//   ata_register_rd
//
// Declaration:
//   uint8 ata_register_rd(t_ata_register_ref r);
//
// Purpose:
//   Read a value from an ata register.
//
// Arguments:
//   r - the t_register_ref identifying the register to be read.
//
// Return:
//   The uint8 to read from the ata register.
//
// Notes:
//   None.
//
// Since:
//   fmc-1.0
//------------------------------------------------------------------------------
uint8 ata_register_rd(t_ata_register_ref r) reentrant
{
  uint8 val;
  _mcu_begin_critical_section();
  _ata_clock_slow();
  // start read cycle, then get data from lsb_ata
  val = *r;
  _nop_(); _nop_(); _nop_();
  val = x_lsb_ata;
  _ata_clock_fast();
  _mcu_end_critical_section();
  return val;
}

//+-----------------------------------------------------------------------------
// Name:
//   ata_read_status
//
// Declaration:
//   uint8 ata_read_status(void);
//
// Purpose:
//   Read the ata status register.
//
// Arguments:
//   None.
//
// Return:
//   The uint8 read from the ata status register.
//
// Notes:
//   Reading the ata status register clears the ata interrupt (in the drive).
//   This function also clears and unmasks the interrupts k_irq_ata and k_irq_fmc_cfc_intrq.
//
// Since:
//   fmc-1.0
//
// History:
//   06/18/02 tbh - modified to leave the ata interrupt masked.
//                - modified this wait_irq_with_timeout to break out if ata irq
//                  bit seen via polling.
//                - this cut about 270usec off the begin burst, decreasing cbw time.
//------------------------------------------------------------------------------
uint8 ata_read_status(void) reentrant;
uint8 ata_read_status() reentrant
{
  uint8 val;
  _mcu_begin_critical_section();
  _ata_clock_slow();
  val = ata_status;
  _nop_(); _nop_(); _nop_();
  val = x_lsb_ata;
  _ata_clock_fast();
  // clear compact flash status as well
  // could do this... but its slower...
  //irq_control(k_irq_fmc_cfc_intrq, kbm_irqctl_clear |kbm_irqctl_unmask);
  x_cfc_stat = kbm_cfc_stat_intrq;
  x_cfc_stat_msk &= ~kbm_cfc_stat_intrq;
  // could do this... but its slower...
  //irq_control(k_irq_ata, kbm_irqctl_clear |kbm_irqctl_unmask);
  x_isr0  = kbm_isr0_ata_irq;
  // 06/18/02 tbh - ata_wait_irq_with_timeout() now polls this bit to avoid
  // the overhead of having the kernel interrupt handler process all of the
  // nested interrupts beneath the fmc/ata irq.  (it takes so long in the isr0
  // handler to check every possible nested source for the ata/fmc irq that
  // it is dramatically faster to just poll the register.
  //x_imr0 &= ~kbm_isr0_ata_irq;
  trace1(0, ata, 99, "status:%02x", val);
  _mcu_end_critical_section();
  return val;
}

//+-----------------------------------------------------------------------------
// Name:
//   ata_reset
//
// Declaration:
//   void ata_reset(void);
//
// Purpose:
//   Perform a hard reset on the ata drive via the reset pin in the ata cable.
//
// Arguments:
//   None.
//
// Return:
//   None.
//
// Notes:
//   This is a FUNCTION, not a DFA.
//
// Since:
//   fmc-1.0
//------------------------------------------------------------------------------
#define kix_ata_reset_pin 0x05
void ata_reset() reentrant
{
  trace0(0, ata, 0, "ata_reset()");
  _mcu_register_set_bits(x_cfc_ata_mode_ctl, kbm_cfc_ata_mode_ctl_dev_rst);
  thread_set_timer(1);
  while(!thread_got_sync(kbm_sync_timer));
  _mcu_register_clr_bits(x_cfc_ata_mode_ctl, kbm_cfc_ata_mode_ctl_dev_rst);
  // spec requires at least 2msec wait here... make sure other code induces wait...
  thread_set_timer(3);
  while(!thread_got_sync(kbm_sync_timer));
}

//+-----------------------------------------------------------------------------
// Name:
//   dfa_ata_reset_media
//
// Declaration:
//   void dfa_ata_reset_media(void);
//

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -