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

📄 ata.c

📁 u盘MCU端源代码,开发U盘的可以参考.
💻 C
📖 第 1 页 / 共 5 页
字号:
// 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
  uint8 i;
  #else
  uint16 i;
  #endif
  uint16 devword;
  //uint8 mode_sel;
  uint8 yes_no_flag;
  trace0(0, ata, 1, "ata_identify_device()");
  _stack_check();
  _thread_clr_sync(kbm_sync_all);

  // select master drive
  ata_register_wr(&ata_device_head, kbm_ata_dev_0);
  // select the identify-device / identify-packet_device function
  ata_register_wr(&ata_command, cmd);
  ata_read_status();
  result = k_error;
  while (k_success != result)  // WARNING! WARNING! DANGER, WILL ROBINSON!!!
  {
    trace1(0, ata, 0, "-- imr0:0x%02X", x_imr0);
    //result = ata_wait_irq_with_timeout(5000);
    result = ata_wait_irq_with_timeout(1000);
    if (k_success != result)
    {
      trace0(0, ata, 1, "ata_identify_device() - error: no irq");
      return k_error;
    }
  }
  trace0(0, ata, 1, "ata_identify_device() - got the ata irq");
  // BSY=0
  status = ata_read_status();
  if (!(status & kbm_ata_status_drq))
  {
    // BSY=0, DRQ=0, therefore command is done
    trace0(0, ata, 1, "ata_identify_device() - warning: drive has no data");
    return k_error;
  }
  // BSY=0, DRQ=1, therefore the drive wants to send more data
  // read the data
  _mcu_begin_critical_section();
  #if 0 // since the bot layer is now a high priority thread at irq level
        // cannot use packet buffers here... switch to using xdata buffer
  _mcu_register_wr(x_sram_addr_lo, k_pkt_addrlo[4]);
  _mcu_register_wr(x_sram_addr_hi, k_pkt_addrhi[4]);
  // there are always 256 words of device data
  for (i=255; i; i--)
  {
    _mcu_register_wr(x_sram_data, ata_register_rd(&ata_data));
    _mcu_register_wr(x_sram_data, _mcu_register_rd(x_msb_ata));
  }
  _mcu_register_wr(x_sram_data, ata_register_rd(&ata_data));
  _mcu_register_wr(x_sram_data, _mcu_register_rd(x_msb_ata));
  #else
  // there are always 256 words of device data
  for (i=0; i<512; i+=2)
  {
    g_sector_buffer[i] = ata_register_rd(&ata_data);

⌨️ 快捷键说明

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