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

📄 ata.c

📁 U盘控制器USB97C223的固件代码,对2kPAGE NAND FLASH 有很好的支持.
💻 C
📖 第 1 页 / 共 5 页
字号:
//     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.
//
// Notes:
//   This is the start STATE of the dfa_ata_read DFA.
//   It overrides dfa_lun_read.
//
// Since:
//   fmc-1.0
//------------------------------------------------------------------------------
void dfa_ata_read(void) reentrant
{
  trace0(0, ata, 0, "dfa_ata_read");
  //_stack_check();
  _fmc_set_callback(fmc_dflt_callback, ata_read_end_xfer,
                    ata_read_begin_split, fmc_dflt_callback,
                    ata_read_begin_burst, fmc_dflt_callback, ata_read_end_burst);
  _fmc_set_options(0);
  //The lexar 512 Mb media supports multiple sectors(4) per interrupt,CF controller
  //hardware supports just 1 sector per interrupt.This causes the RD/WR multiple emulation to
  //break on media's supporting more then 1 sector per interrupt,also the reads works fine
  //on this media cause the Controller state machine does not depend on a IRQ in case of reads
  //hence this code patch is required to ensure a split size of 256 during a read cause it be
  // changed during a write also this a protected by the g_cf_multiple_sectors_per_interrupt
  // flag.
  if (g_cf_multiple_sectors_per_interrupt)
  {
    _lun_data(max_lb_per_split) = 256;
    _lun_data(max_lb_per_burst) = 256;
  }
  dfa_lun_read();
}

//+-----------------------------------------------------------------------------
// Name:
//   ata_write_end_xfer
//
// Declaration:
//   t_result ata_write_end_xfer(void);
//
// Purpose:
//   Turn off multiple emulation if there was an error.
//
// 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_write_end_xfer(void) reentrant;
t_result ata_write_end_xfer() reentrant
{
  trace0(0, ata, 1, "ata_write_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");

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

//+-----------------------------------------------------------------------------
// Name:
//   ata_write_begin_split
//
// Declaration:
//   t_result ata_write_begin_split(void);
//
// Purpose:
//   Issue the write command to the ata drive.
//
// Arguments:
//   None.
//
// Return:
//   A t_result indicating:

⌨️ 快捷键说明

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