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

📄 ata.c

📁 U盘控制器USB97C223的固件代码,对2kPAGE NAND FLASH 有很好的支持.
💻 C
📖 第 1 页 / 共 5 页
字号:
}

//+-----------------------------------------------------------------------------
// 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);
//
// 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 DFA, not a FUNCTION.
//   It overrides dfa_lun_reset.
//
// Since:
//   fmc-1.0
//------------------------------------------------------------------------------
void dfa_ata_reset_media() reentrant
{
  trace0(0, ata, 0, "dfa_ata_reset_media()");
  ata_reset();
  _thread_return_dfa(k_success);
}

//+-----------------------------------------------------------------------------
// Name:
//   ata_poll_status_not_busy
//
// Declaration:
//   void ata_poll_status_not_busy(void);
//
// Purpose:
//   Poll the ata status register to watch for BSY going inactive.
//   When it does deliver kbm_sync_ata_rdy to the active thread.
//
// Arguments:
//   None.
//
// Return:
//   None.
//
// Notes:
//   MinimOS installable thread poller.
//   Watches for synchronizing events that don't have associated interrupts
//   in situations where the thread must yield to avoid blocking other threads.
//   Uninstalls itself when sync delivered to its thread.
//   This is a FUNCTION, not a DFA.
//
// Since:
//   fmc-1.0
//------------------------------------------------------------------------------
void ata_poll_status_not_busy(void) reentrant;
void ata_poll_status_not_busy() reentrant
{
  trace0(0, ata, 90, "ata_poll_status_not_busy()");
  if (!(ata_read_status() & kbm_ata_status_bsy))
  {
    thread_set_sync(g_tid, kbm_sync_ata_rdy);
    thread_set_poller((t_thd_entry)NULL);
  }
}

//+-----------------------------------------------------------------------------
// Name:
//   ata_wait_status_with_timeout
//
// Declaration:
//   t_result ata_wait_status_with_timeout(uint8 mask, uint8 val, uint16 ticks, uint8 *statusp);
//
// Purpose:
//   Poll the ata status register to watch for specific bits matching specific values.
//
// Arguments:
//   mask    - a uint8 with 1's in the bits to be compared
//   val     - a uint8 representing the desired value
//   ticks   - a uint16 representing the timeout limit
//   statusp - a pointer to a uint8, where the value of the status register is returned.
//             statusp can be NULL, in which case no value is returned.
//
// Return:
//   A t_result indicating:
//     k_success - the ata status register logically anded with the mask equals the value.
//     k_usbrst  - usb reset signalling was detected while waiting.
//     k_aborted - traffic occurred on the control pipe while waiting (probably a mass storage reset).
//     k_timeout - timeout limit exceeded.
//
// Notes:
//   This is a FUNCTION, not a DFA.
//
// Since:
//   fmc-1.0
//------------------------------------------------------------------------------
t_result ata_wait_status_with_timeout(uint8 mask, uint8 val, uint16 ticks, uint8 *statusp) reentrant;
t_result ata_wait_status_with_timeout(uint8 mask, uint8 val, uint16 ticks, uint8 *statusp) reentrant
{
  uint8 status;
  t_sync sync;

  trace2(0, ata, 1, "ata_wait_status_with_timeout(mask:0x%02X ticks:%d)", mask, ticks);
  //_stack_check();
  // do this to get kbm_sync_abort delivered of there is traffic on the control pipe
  _isr_bind_dma_owner(g_tid, kbm_sync_none);
  // wait until the device is no longer busy
  thread_set_timer(ticks+1);
  status = ata_read_status();
  do
  {
    sync = thread_got_sync(kbm_sync_abort |kbm_sync_usbrst |kbm_sync_timer);
    _thread_clr_sync(sync);
    if (sync & kbm_sync_usbrst)
    {
      trace0(0, ata, 1, "ata_wait_status_with_timeout() - error: kbm_sync_usbrst");
      return k_usbreset;
    }
    if (sync & kbm_sync_abort)
    {
      trace0(0, ata, 1, "ata_wait_status_with_timeout() - error: kbm_sync_abort");
      return k_aborted;
    }
    if (sync & kbm_sync_timer)
    {
      trace0(0, ata, 1, "ata_wait_status_with_timeout() - error: hung busy");
      return k_timeout;
    }
    status = ata_read_status();
    if (status & kbm_ata_status_err)
    {
      status = ata_register_rd(&ata_error);
      trace1(0, ata, 1, "ata_wait_status_with_timeout() - error: 0x%02X", status);
      return k_error;
    }
  } while ((status & mask) != val);
  if (statusp)
    *statusp = status;
  return k_success;
}

//+-----------------------------------------------------------------------------
// Name:
//   ata_wait_irq_with_timeout
//
// Declaration:
//   t_result ata_wait_irq_with_timeout(uint16 ticks);
//
// Purpose:
//   Poll for the ata interrupt.
//
// Arguments:
//   ticks   - a uint16 representing the timeout limit
//
// Return:
//   A t_result indicating:
//     k_success - the ata interrupt occurred.
//     k_usbrst  - usb reset signalling was detected while waiting.
//     k_aborted - traffic occurred on the control pipe while waiting (probably a mass storage reset).
//     k_timeout - timeout limit exceeded.
//
// Notes:
//   This is a FUNCTION, not a DFA.
//
// Since:
//   fmc-1.0
//
// History:
//   06/18/02 tbh - modified ata_read_status() to leave the ata interrupt masked.
//                - modified this routine to break out if ata irq bit seen via polling.
//                - this cut about 270usec off the begin burst, decreasing cbw time.
//------------------------------------------------------------------------------
t_result ata_wait_irq_with_timeout(uint16 ticks) reentrant;
t_result ata_wait_irq_with_timeout(uint16 ticks) reentrant
{
  t_sync sync;

  trace1(0, ata, 1, "ata_wait_irq_with_timeout(ticks:%d)", ticks);
  //_stack_check();
  // do this to get kbm_sync_abort delivered of there is traffic on the control pipe
  _isr_bind_dma_owner(g_tid, kbm_sync_none);
  thread_set_timer(ticks+1);
  do
  {
    sync = thread_got_sync(kbm_sync_abort |kbm_sync_usbrst |kbm_sync_timer |kbm_sync_ata_irq);
    _thread_clr_sync(sync);
    if (sync & kbm_sync_usbrst)
    {
      trace0(0, ata, 1, "ata_wait_irq_with_timeout() - error: kbm_sync_usbrst");
      return k_usbreset;
    }
    if (sync & kbm_sync_abort)
    {
      trace0(0, ata, 1, "ata_wait_irq_with_timeout() - error: kbm_sync_abort");
      return k_aborted;
    }
    if (sync & kbm_sync_timer)
    {
      trace0(0, ata, 1, "ata_wait_irq_with_timeout() - error: timeout awaiting irq");
      return k_timeout;
    }
    if (_mcu_register_rd(x_isr0) & kbm_isr0_ata_irq) break;
  } while (!(sync & kbm_sync_ata_irq));
  trace0(0, ata, 1, "ata_wait_irq_with_timeout() - got the ata irq");
  return k_success;
}

extern xdata uint8 g_sector_buffer[];
//+-----------------------------------------------------------------------------
// Name:
//   iddev_word
//
// Declaration:
//   static uint16 iddev_word(uint16 word_offset);
//
// Purpose:
//   Build a 16 bit word by extracting 2 bytee from pnr 4 at the specified offset.
//
// Arguments:
//   word_offset - a uint16 specifying the offset into pnr 4 to get the result from.
//
// Return:
//   A uint16 containing the 2 bytes extracted from pnr 4.
//
// Notes:
//   This is a FUNCTION, not a DFA.
//
// Since:
//   fmc-1.0
//------------------------------------------------------------------------------
static uint16 iddev_word(uint16 word_offset) reentrant;
static uint16 iddev_word(uint16 word_offset) reentrant
{
  uint16 byte_offset;
  t_uw16 word;

  byte_offset = 2 * word_offset;
  #if 0
  _mcu_register_wr(x_sram_addr_lo, k_pkt_addrlo[4] + _l(byte_offset));
  _mcu_register_wr(x_sram_addr_hi, k_pkt_addrhi[4] + _h(byte_offset));
  word.u8.lo = _mcu_register_rd(x_sram_data);
  word.u8.hi = _mcu_register_rd(x_sram_data);
  #else
  word.u8.lo = g_sector_buffer[byte_offset++];
  word.u8.hi = g_sector_buffer[byte_offset];
  #endif
  return word.u16;
}

//+-----------------------------------------------------------------------------
// Name:
//   ata_identify_device
//
// Declaration:
//   void ata_identify_device(uint8 cmd);
//
// Purpose:
//   Poll the ata status register to watch for specific bits matching specific values.
//
// Arguments:
//   cmd - a uint8 representing the "identify" command to issue to the drive.
//
// Return:
//   A t_result indicating:
//     k_success - device successfully identified.
//     k_error   - device failed to identify in a potentially recoverable way.
//   OR
//     No return - dfa ends on unrecoverable error.
//
// Notes:
//   This is a FUNCTION, not a DFA, but must be called from within a DFA.
//
// Since:
//   fmc-1.0
//------------------------------------------------------------------------------
t_result ata_identify_device(uint8 cmd) reentrant
{
  uint8 status;
  t_result result;
  #if 0

⌨️ 快捷键说明

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