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

📄 ideutils.c

📁 MP3 Cyclone的source code 利用FPGGA實現MP3的功能
💻 C
📖 第 1 页 / 共 4 页
字号:
/**********************************************
Utilities for IDE

This file is an example of IDE functionality.

Hardware resources required:
1 system timer
1 memory-mapped IDE port, with interrupt.

**********************************************/

#include "system.h"
#include "altera_avalon_timer.h"
#include "altera_avalon_cf_regs.h"

#ifndef CF_IDE_BASE
#error This IDE utility requires a CompactFlash Interface component named "cf"
#endif

#if ALT_SYS_CLK_BASE == none_BASE
#error This IDE utility requires a system clock with millisecond frequency
#endif


#include "sys/alt_alarm.h"
#include "sys/alt_irq.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include "ideutils.h"

#define DEBUG 0
#define DEBUGPRINT 0

#define IDEUTILS_printf(x) printf##x

#define getTime() alt_nticks()

#define ctl_base (int*)CF_CTL_BASE
#define ctl_irq  (int)CF_CTL_IRQ
#define ide_base (int*)CF_IDE_BASE
#define ide_irq  (int)CF_IDE_IRQ


// Exactly one IDE drive is assumed: these globals store parameters
// of that drive.
unsigned short gusLogicalHeads = 0,
  gusLogicalCylinders = 0,
  gusSectorsPerTrack = 0;

unsigned short gusPIOmode = 0;
unsigned short gusLBAmode = 0;
unsigned long  gulLBAcapacity = 0;

unsigned char gModel[40+1];

volatile int IDEinterrupt = 0;
volatile int giMediaChanged = 0;

int gbVerbose = 1;

int IDE_getVerbosity(void)
{
  return gbVerbose;
}

void IDE_setVerbosity(int iVerbosity)
{
  gbVerbose = iVerbosity;
}



// controller interrupt routines

void IDETrapHandler(void* context, alt_u32 id)
{
	IORD_ALTERA_AVALON_CF_IDE_STATUS(ide_base);  // (To clear INTRQ)
	IDEinterrupt = 1;
}


void CTLTrapHandler(void* context, alt_u32 id)
{
  giMediaChanged = 1;
  if (IORD_ALTERA_AVALON_CF_CTL_STATUS(ctl_base)
            & ALTERA_AVALON_CF_CTL_STATUS_PRESENT_MSK)
  {
    //printf("CompactFlash inserted\n");
  }
  else
  {
    //printf("CompactFlash removed\n");
  }
}


int MediaChanged(void)
{
  if (giMediaChanged)
  {
    giMediaChanged = 0;
    return 1;
  }
  return 0;
}

// timed functions
int awaitBSYZeroOrINTRQ(int iMS)
{
  unsigned int uiSuccess;
  unsigned int uiStartTime;
  volatile unsigned int uiDeltaTime;

  uiSuccess = 0;
  uiStartTime = getTime();
  do
  {
    if (0 ==
      (IORD_ALTERA_AVALON_CF_IDE_ALTERNATE_STATUS(ide_base) & AltStatusRegBitBSY))
    {
      uiSuccess = 1;
      break;
    }

	if (IDEinterrupt == 1)
    {
      IDEinterrupt = 0;
      uiSuccess = 1;
      break;
    }

    uiDeltaTime = getTime() - uiStartTime;
  } while (uiDeltaTime < iMS);

  return uiSuccess;
}

int awaitDRQ(int iMS)
{
  unsigned int uiSuccess;
  volatile unsigned int uiStartTime, uiDeltaTime;
  unsigned short usStatus;

  uiSuccess = 0;
  uiStartTime = getTime();
  while ((uiDeltaTime = getTime() - uiStartTime) < iMS)
  {

    usStatus = IORD_ALTERA_AVALON_CF_IDE_ALTERNATE_STATUS(ide_base);

    // i) If DRQ=1, the host transfers a block of data by reading the Data register.
    //    If any error conditions are present in the status read in step h), the
    //    data transfer may not be valid.
    if (usStatus & AltStatusRegBitDRQ)
    {
      uiSuccess = 1;
      break;
    }
  }

  if (!uiSuccess)
  {
    printf("timeout awaiting DRQ=1\r");
    printf("error register: 0x%X\r", IORD_ALTERA_AVALON_CF_IDE_ERROR(ide_base));
    return 0;
  }

#if DEBUG
  printf("DRQ found after %d ms\r", uiDeltaTime);
#endif // DEBUG
  return uiSuccess;
}

int awaitINTRQ(int iMS)
{
  unsigned int uiSuccess;
  volatile unsigned int uiStartTime, uiDeltaTime;

  uiSuccess = 0;
  uiStartTime = getTime();
  while ((uiDeltaTime = getTime() - uiStartTime) < iMS)
  {
	if (IDEinterrupt == 1)
    {
      IDEinterrupt = 0;
      uiSuccess = 1;
      break;
    }
  }

  if (!uiSuccess)
  {
    printf("timeout awaiting INTRQ=1\r");
    printf("error register: 0x%X\r", IORD_ALTERA_AVALON_CF_IDE_ERROR(ide_base));
    return 0;
  }

#if DEBUG
  printf("INTRQ found after %d ms\r", uiDeltaTime);
#endif // DEBUG
  return uiSuccess;
}

int awaitBSYZero(unsigned int uiTimeout)
{
  unsigned int uiSuccess;
  unsigned int uiStartTime;
  volatile unsigned int uiDeltaTime;

  uiSuccess = 0;
  uiStartTime = getTime();
  do
  {
    if (0 ==
      (IORD_ALTERA_AVALON_CF_IDE_ALTERNATE_STATUS(ide_base) & AltStatusRegBitBSY))
    {
      uiSuccess = 1;
      break;
    }

    uiDeltaTime = getTime() - uiStartTime;
  } while (uiDeltaTime < uiTimeout);

  return uiSuccess;
}

int awaitBSYOne(unsigned int uiTimeout)
{
  unsigned int uiSuccess;
  volatile unsigned int uiStartTime, uiDeltaTime;

  uiSuccess = 0;
  uiStartTime = getTime();
  while ((uiDeltaTime = getTime() - uiStartTime) < uiTimeout)
  {
    if (1 == !!(IORD_ALTERA_AVALON_CF_IDE_ALTERNATE_STATUS(ide_base) & AltStatusRegBitBSY))
    {
      uiSuccess = 1;
      break;
    }
  }

  return uiSuccess;
}

int awaitBSYZeroDRDYOne(void)
{
  unsigned short r;
  unsigned int uiSuccess;
  volatile unsigned int uiStartTime, uiDeltaTime;

  uiSuccess = 0;
  uiStartTime = getTime();
  while ((uiDeltaTime = getTime() - uiStartTime) < 10)
  {
    r = IORD_ALTERA_AVALON_CF_IDE_ALTERNATE_STATUS(ide_base);

    if ((r & (AltStatusRegBitBSY | AltStatusRegBitDRDY)) ==
      AltStatusRegBitDRDY)
    {
      uiSuccess = 1;
      break;
    }
  }

  if (!uiSuccess)
  {
    return 0;
  }
  return uiSuccess;
}


// Wrapper functions for IDE commands.
int softwareReset(unsigned int uiDeviceNumber)
{
  volatile unsigned int uiStartTime;
  unsigned int uiSuccess;

  // Select the device to reset.
  if (uiDeviceNumber > 1)
  {
    printf("invalid device number in softwareReset (%d)\n",
      uiDeviceNumber);
    return 0;
  }

  IOWR_ALTERA_AVALON_CF_IDE_DEVICE_HEAD(ide_base, uiDeviceNumber ? DevHeadRegBitDEV : 0);

  // Host sets the SRST bit to 1 in the Device Control register.
  // (Note: interrupt is enabled.)
  IOWR_ALTERA_AVALON_CF_IDE_DEVICE_CONTROL(ide_base, (DevControlRegBitSRST | DevControlRegBitNIEN));

  // Device 0 sets BSY bit no later than 400ns after detection of SRST=1
  // (I give it ~10ms.)

  if (!awaitBSYOne(100))
  {
    printf("timeout awaiting BSY=1 in softwareReset()\n");
    return 0;
  }
#if DEBUG
  else
  {
    printf("found BSY=1\n");
  }
#endif // DEBUG

  // Device 0 performs hardware init and diag
  // Dev0 may revert to its default condition
  // Dev0 posts diag results to the Error Register

  // Hm.  How am I supposed to know when the diag results have arrived?
  // There seems to be no handshaking, so I'll assume I can set SRST=0 any
  // old time.

  // Dev0 waits for the host to set SRST=0.
  IOWR_ALTERA_AVALON_CF_IDE_DEVICE_CONTROL(ide_base, DevControlRegBitNIEN);

  // (If a device 1 is expected, some lengthy drive-to-drive communication may occur)
  // If no device was detected previously, bit 7 of Error Register set to 0.
  // The device sets
  //   Sector Count to 01,
  //   Sector Number to 01,
  //   Cylinder Low register to 0,
  //   Cylinder High register to 0,
  //   Device/Head register to 0.
  // Device 0 clears the BSY bit when ready to accept commands that do not require
  // DRDY to be 1 (no later than 31 seconds from the time that the host sets SRST=0).

  // (watch for the BSY=0)
  if (!awaitBSYZero(1000))
  {
    printf("timeout awaiting BSY=0 in softwareReset()\n");
    return 0;
  }
#if DEBUG
  printf("found BSY=0\n");
#endif // DEBUG

  // Device 0 sets DRDY when ready to accept any command.
  uiSuccess = 0;
  uiStartTime = getTime();
  while (getTime() - uiStartTime < 1000)
  {
    if (IORD_ALTERA_AVALON_CF_IDE_ALTERNATE_STATUS(ide_base) & AltStatusRegBitDRDY)
    {
      uiSuccess = 1;
      break;
    }
  }

  if (!uiSuccess)
  {
    printf("timeout awaiting DRDY=1 in softwareReset()\n");
    return 0;
  }
#if DEBUG
//  printf("found DRDY=1 after %d ms\r", uiDeltaTime);
#endif // DEBUG

#if DEBUG
  // Verify sector count = 1,
  //        sector number = 1,
  //        cylinder low = 0,
  //        cylinder high = 0,
  //        dev/head reg = 0.
  printf("status register: 0x%X\r", IORD_ALTERA_AVALON_CF_IDE_STATUS(ide_base));
  printf("sector count:  0x%X\r", IORD_ALTERA_AVALON_CF_IDE_SECTOR_COUNT(ide_base));
  printf("sector number: 0x%X\r", IORD_ALTERA_AVALON_CF_IDE_SECTOR_NUMBER(ide_base));
  printf("cylinder low:  0x%X\r", IORD_ALTERA_AVALON_CF_IDE_CYLINDER_LOW(ide_base));
  printf("cylinder high: 0x%X\r", IORD_ALTERA_AVALON_CF_IDE_CYLINDER_HIGH(ide_base));
  printf("device/head:   0x%X\r", IORD_ALTERA_AVALON_CF_IDE_DEVICE_HEAD(ide_base));
#else // !DEBUG
  if (
    (0xFF & IORD_ALTERA_AVALON_CF_IDE_STATUS(ide_base)) != 0x50 ||
    (0xFF & IORD_ALTERA_AVALON_CF_IDE_SECTOR_COUNT(ide_base)) != 1 ||
    (0xFF & IORD_ALTERA_AVALON_CF_IDE_SECTOR_NUMBER(ide_base)) != 1 ||
    (0xFF & IORD_ALTERA_AVALON_CF_IDE_CYLINDER_LOW(ide_base)) != 0 ||
    (0xFF & IORD_ALTERA_AVALON_CF_IDE_CYLINDER_HIGH(ide_base)) != 0 ||
    (0xFF & IORD_ALTERA_AVALON_CF_IDE_DEVICE_HEAD(ide_base)) != 0)
  {
    printf("software reset command failed.\r");
  }
  else
  {
    printf("software reset command succeeded.\r");
  }

#endif // DEBUG
  return 1;
}


int PIODataInOrOutPreamble(int iDevice)
{
  // Select the device to identify.
  if (iDevice > 1)
  {
    printf("invalid device number in PIODataInOrOut(%d)\r",
      iDevice);
    return 0;
  }

  // a) The host reads the status or alt status reg until BSY=0.
  if (!awaitBSYZero(1000))
  {
    printf("timeout (1) awaiting BSY=0 in PIODataInOrOut()\r");
    return 0;
  }

  // b) The host writes the dev/head register with the appropriate dev
  //    bit value.
  IOWR_ALTERA_AVALON_CF_IDE_DEVICE_HEAD(ide_base, iDevice ? DevHeadRegBitDEV : 0);

  // c) The host reads the status or alt status register until BSY=0 and
  //    DRDY=1.
  if (!awaitBSYZeroDRDYOne())
  {
    printf("timeout awaiting BSY=0, DRDY=1 in PIODataInOrOut()\r");
    return 0;
  }

  return 1;
}

  // PIO Data In:
  // a) The host reads the status or alt status reg until BSY=0.
  // b) The host writes the dev/head register with the appropriate dev
  //    bit value.
  // c) The host reads the status or alt status register until BSY=0 and
  //    DRDY=1.
  // d) The host writes any required command parameters to the Features,
  //    Sector Count, Sector Number, Cylinder High, Cylinder Low and
  //    Device/Head registers.
  // e) The host writes the command code to the Command register.
  // f) The device sets the BSY bit and prepares to execute the command
  //    including preparation to transfer the first block of data to the
  //    host.  (Note: it may take up to 400ns for BSY to go high.)
  // g) When the block of data is available, the device sets the DRQ bit
  //    (setting the DRQ bit is optional if an error condition exists).
  //    If there is an error condition, the device sets the appropriate status
  //    and error bits as required by that error condition.  Finally, the device
  //    clears BSY and then asserts INTRQ.  (Note: there may be times when BSY
  //    is set in f) and then cleared in g) so quickly that the host may not
  //    be able to detect that BSY had been set.)
  // h) After detecting either BSY=0 (alt status) or INTRQ, the host reads and
  //    saves the contents of the status register.
  // i) If DRQ=1, the host transfers a block of data by reading the Data register.
  //    If any error conditions are present in the status read in step h), the
  //    data transfer may not be valid.
  // j) When the status register is read, the device negates INTRQ.  In response to
  //    the complete data block being read, one of the following actions is taken:
  //    - if no error status was presented to the host in step h), and if transfer
  //      of another block is required, the device sets BSY and the above sequence
  //      is repeated starting from step g).
  //    - If an error status was present in the status read in step h), the device
  //      clears DRQ and the command execution is complete.
  //    - If the last block was transfered, the device clears DRQ and the command
  //      execution is complete.

int readSectorsCHSResult(int iSectorCount, unsigned short *pusBuffer)
{
  unsigned short usStatus;
  int iSect;
  int i, iIndex;

  // f) The device sets the BSY bit and prepares to execute the command
  //    including preparation to transfer the first block of data to the
  //    host.  (Note: it may take up to 400ns for BSY to go high.)
  // g) When the block of data is available, the device sets the DRQ bit
  //    (setting the DRQ bit is optional if an error condition exists).
  //    If there is an error condition, the device sets the appropriate status
  //    and error bits as required by that error condition.  Finally, the device
  //    clears BSY and then asserts INTRQ.  (Note: there may be times when BSY
  //    is set in f) and then cleared in g) so quickly that the host may not
  //    be able to detect that BSY had been set.)
  for (iSect = 0; iSect < iSectorCount; ++iSect)
  {
    if (!awaitDRQ(1000))
    {
      printf("timeout awaiting DRQ in readSectorsCHS()\r");
    }

    if (!awaitBSYZero(1000))
    {
      printf("timeout (2) awaiting BSY=0 in readSectorsCHS()\r");
      return 0;
    }

    if (!awaitINTRQ(5000))
    {
      printf("timeout awaiting INTRQ=1 in readSectorsCHS()\r");
      printf("error register: 0x%X\r", IORD_ALTERA_AVALON_CF_IDE_ERROR(ide_base));
      return 0;
    }

    // h) After detecting either BSY=0 (alt status) or INTRQ, the host reads and
    //    saves the contents of the status register.
    usStatus = IORD_ALTERA_AVALON_CF_IDE_STATUS(ide_base); // (To clear INTRQ)

⌨️ 快捷键说明

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