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

📄 ata.c

📁 u盘MCU端源代码,开发U盘的可以参考.
💻 C
📖 第 1 页 / 共 5 页
字号:
    _thread_clr_sync(kbm_sync_ata_rdy);
    trace1(0, ata, 0, "-- after _lun_data:0x%02X", x_imr0);
    #ifdef k_mcu_97201
    // setup IDE timing register - compatible PIO, fast time for non-udma dma only
    _mcu_register_clr_bits(x_ide_tim, kbm_ide_tim_dte);  //clear bit 3 dte so both MWDMA and PIO transfers use fast timing mode
    _mcu_register_set_bits(x_ide_tim, (kbm_ide_tim_ftb |k_ide_iordy_3clocks |k_ide_recover_1clocks));
    #endif
    // check for diagnostic results
    error = ata_register_rd(&ata_error);
    switch (error)
    {
      case 0x00:
        trace0(0, ata, 0, "ata_initialize_media2() - error: no unit found");
        break;
      case 0x01:
        trace0(0, ata, 0, "ata_initialize_media2() - DEV0 Passed, DEV1 Passed/Not Present");
        break;
      case 0x81:
        trace0(0, ata, 0, "ata_initialize_media2() - DEV0 Passed, DEV1 Failed");
        break;
      default:
        trace1(0, ata, 0, "ata_initialize_media2() - error: diagnostic:0x%02X", error);
        break;
    }
    // check for a signature telling us what type of device we have
    sector_cnt = ata_register_rd(&ata_sector_cnt);
    sector_num = ata_register_rd(&ata_sector_num);
    cylinder_lo = ata_register_rd(&ata_cylinder_lo);
    cylinder_hi = ata_register_rd(&ata_cylinder_hi);
    trace4(0, ata, 0, "dev signature: sc:0x%02X sn:0x%02X cl:0x%02X sh:0x%02X", sector_cnt, sector_num, cylinder_lo, cylinder_hi);
    // check for ATA
    if (sector_cnt == 0x01 && sector_num == 0x01 && cylinder_lo == 0x00 && cylinder_hi == 0x00)
    {
      trace0(0, ata, 0, "ata_initialize_media2() - lun is ATA");
      _lun_data_wr(k_lun_ata, media, (_lun_data_rd(k_lun_ata, media)&~kbm_lun_media_changed)); 

      // m'kay - here is the biggest optimization yet...
      // use pio mode 4 instead of the default mode 0 and viola...
      // 1.1R:960K 1.1W:923K 2.0R:5.57M 2.0W:3.37M
      // it is safe to or in the mode bits ONLY because this is after POR and the por value is 0
      // if it was done elsewhere it would need to be

      // $$$ cds -> 4 not working for some devices... set it to 0 until media is identified
      // 0x07 is the mask that covers all modes
      // _mcu_register_clr_bits(x_cfc_ata_mode_ctl, k_cfc_ata_mode_4);

      _thread_return_dfa(k_success);
    }
    trace0(0, ata, 0, "ata_initialize_media2() - error: bad signature - cannot identify device");
    _thread_return_dfa(k_error);
  }
  dev_exception(k_err_unreachable_code+11);
}

//+-----------------------------------------------------------------------------
// Name:
//   dfa_ata_initialize_media
//
// Declaration:
//   void dfa_ata_initialize_media(void);
//
// Purpose:
//   Setup to detect the BSY bit clearing, then yield hoping to initialize the ata drive.
//
// Arguments:
//   None.
//
// Return:
//   No return value.
//   However, on exit the DFA's argument pointer is written with a t_result indicating:
//     k_success - command completed.
//     k_usbrst  - usb reset signalling was detected while executing the command.
//     k_aborted - traffic occurred on the control pipe while wexecuting the command (probably a mass storage reset).
//     k_timeout - a timeout limit exceeded while executing the command.
//   (This allows the caller to see the return value, via the argp, after the DFA terminates).
//
// Notes:
//   This is the start STATE of the dfa_ata_initialize_media DFA.
//   It overrides dfa_lun_initialize.
//
// Since:
//   fmc-1.0
//------------------------------------------------------------------------------
void dfa_ata_initialize_media() reentrant
{
  trace0(0, ata, 1, "dfa_ata_initialize_media()");
  //read status to clear a pending irq, and to reset isr&imr 0
  ata_read_status();
  thread_set_poller((t_thd_entry)ata_poll_status_not_busy);
  thread_yield_ex(kbm_sync_none, kbm_sync_ata_rdy, ata_initialize_media2);
}

//+-----------------------------------------------------------------------------
// Name:
//   ata_read_end_xfer
//
// Declaration:
//   t_result ata_read_end_xfer(void);
//
// Purpose:
//   Wait until the drive is not busy.
//
// Arguments:
//   None.
//
// Return:
//   A t_result indicating:
//     k_success - done.
//     k_usbrst  - usb reset signalling was detected while executing the command.
//     k_aborted - traffic occurred on the control pipe while wexecuting the command (probably a mass storage reset).
//     k_timeout - a timeout limit exceeded while executing the command.
//
// Notes:
//   This is a FUNCTION, not a DFA.
//   Do not yeild, or run a DFA, from within this callback.
//
// Since:
//   fmc-1.0
//------------------------------------------------------------------------------
t_result ata_read_end_xfer(void) reentrant;
t_result ata_read_end_xfer() reentrant
{
  t_result rslt;
  uint8 status;

  trace0(0, ata, 1, "ata_read_end_xfer()");
  _stack_check();
  // turn off the multiple emulation bit
  _mcu_register_clr_bits(x_cfc_ata_mode_ctl, kbm_cfc_ata_mode_ctl_mult_emu_en);
  trace0(0, ata, 0, "multiple emulation off");
  if (k_success != _fmc_get_result())
    return _fmc_get_result();
  status = ata_read_status();
  if (status & kbm_ata_status_err)
    return k_error;
  if (status & (kbm_ata_status_bsy |kbm_ata_status_drq))
    if (k_success != (rslt = ata_wait_status_with_timeout(kbm_ata_status_bsy |kbm_ata_status_drq, 0, 5000, NULL)))
      return rslt;
  return k_success;
}

//+-----------------------------------------------------------------------------
// Name:
//   ata_read_begin_split
//
// Declaration:
//   t_result ata_read_begin_split(void);
//
// Purpose:
//   Issue the read command to the ata drive.
//
// Arguments:
//   None.
//
// Return:
//   A t_result indicating:
//     k_success - command completed.
//
// Notes:
//   This is a FUNCTION, not a DFA.
//   Do not yeild, or run a DFA, from within this callback.
//
// Since:
//   fmc-1.0
//------------------------------------------------------------------------------
t_result ata_read_begin_split(void) reentrant;
t_result ata_read_begin_split() reentrant
{
  t_udw32 start_lb;
  t_udw32 lb_count;

  trace0(0, ata, 1, "ata_read_begin_split()");
  _stack_check();
  _fmc_set_options(0);
  _fmc_set_timeout(10000);
  start_lb.u32 = _fmc_get_start_lb_32();
  lb_count.u32 = _fmc_get_lb_count_32();

  // clear any stale ata irq
  ata_read_status();
  _ata_register_wr(&ata_device_head,
                  (kbm_ata_dev_lba|
                   (start_lb.u8.hi & kbm_msk_ata_dev_lba_hi)));
  _ata_register_wr(&ata_cylinder_hi, start_lb.u8.lh);
  _ata_register_wr(&ata_cylinder_lo, start_lb.u8.hl);
  _ata_register_wr(&ata_sector_num,  start_lb.u8.lo);
  _ata_register_wr(&ata_sector_cnt, lb_count.u8.lo);
  _ata_register_wr(&ata_command, k_ata_command_read_sectors);
  return k_success;
}

//+-----------------------------------------------------------------------------
// Name:
//   ata_read_begin_burst
//
// Declaration:
//   t_result ata_read_begin_burst(void);
//
// Purpose:
//   Issue the read command to the ata drive.
//
// Arguments:
//   None.
//
// Return:
//   A t_result indicating:
//     k_success - ready to transfer data.
//     k_usbrst  - usb reset signalling was detected while executing the command.
//     k_aborted - traffic occurred on the control pipe while wexecuting the command (probably a mass storage reset).
//     k_timeout - a timeout limit exceeded while executing the command.
//
// Notes:
//   This is a FUNCTION, not a DFA.
//   Do not yeild, or run a DFA, from within this callback.
//
// Since:
//   fmc-1.0
//------------------------------------------------------------------------------
t_result ata_read_begin_burst(void) reentrant;
t_result ata_read_begin_burst() reentrant
{
  uint8 status;
  t_result rslt;

  trace0(0, ata, 1, "ata_read_begin_burst()");
  _stack_check();
  // wait for the drive to interrupt

  // NOTE: this 'optimization' seems to slow it down
  //rslt = k_success;
  //if (!_thread_got_sync(kbm_sync_ata_irq))

  // it takes about 250 usec minimum to get the interrupt...
  // on the 24x lexar 256mb card (the fastest yet seen)
  if (k_success != (rslt = ata_wait_irq_with_timeout(5000)))
    return rslt;

  // NOTE: this optimization speeds it up
  status = ata_read_status();
  if (status & kbm_ata_status_err)
    return k_error;
  if (status & kbm_ata_status_drq != kbm_ata_status_drq)
    // poll the status register until the drq bit goes active
    rslt = ata_wait_status_with_timeout(kbm_ata_status_drq, kbm_ata_status_drq, 5000, &status);
  if (k_error == rslt)
  {
    // error... put in the appropriate sense code
    trace0(0, ata, 0, "sense_read_error");
    _lun_data_wr(k_lun_ata, sensep, &sense_read_error);
    return k_error;
  }
  // some other error waiting for the drq
  if (k_success != rslt)
    return rslt;

  // mask the isr from the cf device
  _mcu_register_set_bits(x_cfc_stat_msk, kbm_cfc_stat_intrq);

  // turn on the multiple emulation bit
  _mcu_register_set_bits(x_cfc_ata_mode_ctl, kbm_cfc_ata_mode_ctl_mult_emu_en);

  trace0(0, ata, 0, "multiple emulation on");

  // got the drq
  return k_success;
}

//+-----------------------------------------------------------------------------
// Name:
//   ata_read_end_burst
//
// Declaration:
//   t_result ata_read_end_burst(void);
//
// Purpose:
//   Issue the read command to the ata drive.
//
// Arguments:
//   None.
//
// Return:
//     k_success - ready to transfer data.
//
// Notes:
//   This is a FUNCTION, not a DFA.
//   Do not yeild, or run a DFA, from within this callback.
//
// Since:
//   fmc-1.0
//------------------------------------------------------------------------------
t_result ata_read_end_burst(void) reentrant;
t_result ata_read_end_burst() reentrant
{
  t_result rslt;

  trace0(0, ata, 0, "ata_read_end_burst()");
  // turn off the multiple emulation bit
  _mcu_register_clr_bits(x_cfc_ata_mode_ctl, kbm_cfc_ata_mode_ctl_mult_emu_en);
  trace0(0, ata, 0, "multiple emulation off");
  _stack_check();
  _mcu_register_clr_bits(x_cfc_ata_mode_ctl, kbm_cfc_ata_mode_ctl_mult_emu_en);

  // check to see if the fmc xfer was aborted... if so, reset the drive and return k_aborted
  rslt = _fmc_get_result();
  if( rslt != k_success )
  {
    trace0(0, ata, 0, "fmc xfer was aborted.  reset the device to stop it");
    ata_reset();
  }
  return rslt;
}


//+-----------------------------------------------------------------------------
// Name:
//   dfa_ata_read
//
// Declaration:
//   void dfa_ata_read(void);
//
// Purpose:
//   Read data from an ata drive.
//
// Arguments:
//   None.
//   Uses _lun_data and g_bot_cbw to get its parameters.
//
// Return:
//   No return value.
//   However, on exit the DFA's argument pointer is written with a t_csw_status indicating:
//     k_command_passed - command completed.
//     k_command_failed - an error occurred.

⌨️ 快捷键说明

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