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

📄 gpif.c

📁 Cy68013的应用——USB2.0接口转IDE、CF卡接口
💻 C
字号:
//-----------------------------------------------------------------------------
//  Copyright (c) 1999-2002 Cypress Semiconductor, Inc. All rights reserved
//-----------------------------------------------------------------------------
//
// This file contains GPIF support code.  
//
// $Workfile: gpif.c $
// $Date: 6/24/02 4:02p $
// $Revision: 13 $
//-----------------------------------------------------------------------------
#pragma ot(8,SPEED) // keep gpif.c at Optimization Level 8 (no re-ordering)
					// This is because some DVD-RAM drives had a problem when a common
					// subroutine was replaced. The problem appeared to be only a minor
					// difference in timing. The DVD-RAM drive would fail if a subroutine
					// call was added to readPIO8. It reported a residue of data after
					// a prior transfer had been completed, and when that data was read,
					// it was just a buffer filled with invalid (repeating) data.
					// The problem appeared to be the fault of the DVD-ROM drive.

#include <scsi.h>
#include "fx2.h"
#include "fx2regs.h"
#include "gpif.h"
#include "globals.h"


//
// Do not edit the following waveform array!  Use the GPIF utility to edit the file
// GPIFPIO4.C.  Once modifications are made there, paste the resulting waveform
// array into this file.
//
// Don't forget that the IORDY signal can be produced at the drive up to 35ns after we
// drop RD or WR.  It then takes 2 clocks for us to demet the signal (async input).  The
// IORDY signal is available on the FIFTH clock edge after RD or WR is dropped.
// Edge 1)  Drop RD/WR (start state 0)
// Edge 2)  No action
// Edge 3)  IORDY detected at first flop
// Edge 4)  IORDY detected at second flop
// Edge 5)  IORDY available as an input to IF/THEN statements. (start state 1)
//
//
//

const char code WaveDataPioUDMA[128] =                                                           
{                                                                                          
// Wave 0    (Write PIO0)
// State 0 -- Drive DIOW Low (output = FE), Drive data bus (opcode = 2), Length = 0xa (10 clocks = 210nsec)
// State 1 -- Drive DIOW Low (output = FE), Drive data bus (opcode = 2), Length = 0x2 (2 clocks = 41ns)
// State 2 -- Drive DIOW High (output = FF),Drive data bus (opcode = 2), Length = 0x12(18 clocks = 375ns)
// State 3 -- Branch to end, continue driving data, use FIFO flag as branch
/* LenBr */ 0x0a,     0x02,     0x12,     0x3F,     /* PIO4 LENBR ges */ 0x03, 0x11, 0x01, 0x3f,
/* Opcode*/ 0x02,     0x02,     0x02,     0x07,     /* Opcode Changes */ 0x02, 0x03, 0x02, 0x07,
/* Output*/ 0xFE,     0xFE,     0xFF,     0xFF,     /* CF LenBr */       0x07, 0x11, 0x01, 0x3f,
/* LFun  */ 0x00,     0x00,     0x00,     0x36,     /* CF Opcod */       0x02, 0x03, 0x02, 0x07,
// Wave 1                                                                                  
/* LenBr */ 0x04,     0x04,     0x16,     0x3f,     /* PIO4 LENBR */ 0x03, 0x11, 0x3f, 0x00,
/* Opcode*/ 0x00,     0x00,     0x06,     0x01,     /* PIO4 opcode*/ 0x00, 0x01, 0x07, 0x00,
/* Output*/ 0xFD,     0xFD,     0xFF,     0xFF,     /* CF LenBr */   0x05, 0x11, 0x04, 0x3f,
/* LFun  */ 0x00,     0x00,     0x00,     0x00,     /* CF Opcod */   0x00, 0x01, 0x06, 0x01,
// Wave 0  UDMA Write
/* LenBr */ 0x08,     0x01,     0x06,     0x1C,     0x01,     0x01,     0x02,     0x07,    
/* Opcode*/ 0x01,     0x00,     0x02,     0x03,     0x02,     0x02,     0x26,     0x00,    
/* Output*/ 0xFF,     0xFB,     0xFA,     0xFA,     0xF8,     0xFB,     0xFB,     0xFF,    
/* LFun  */ 0x09,     0x09,     0x12,     0x09,     0x00,     0x2d,     0x36,     0x3F,     
// Wave 1  UDMA Read
/* LenBr */ 0x08,     0x01,     0x13,     0x01,     0x01,     0x02,     0x01,     0x07,    
/* Opcode*/ 0x01,     0x00,     0x01,     0x00,     0x00,     0x26,     0x26,     0x00,    
/* Output*/ 0xFF,     0xFB,     0xF8,     0xFB,     0xFB,     0xFB,     0xFF,     0xFF,    
/* LFun  */ 0x09,     0x09,     0x09,     0x1b,     0x00,     0x2D,     0x36,     0x3F,    
};                                                                                         

#if COMPACT_FLASH
void cfHardwareReset()
{
   OEA |= CF_RESET;
   OUTATAPI |= CF_RESET;
   EZUSB_Delay(100);
   OUTATAPI &= ~CF_RESET;
   OEA &= ~CF_RESET;
}
#endif

void hardwareReset()
{
   #if COMPACT_FLASH
   cfHardwareReset();
   #endif

   OEA |= ATAPI_RESET_;    // Needed for revC board.  Doesn't hurt for old pinout.
   OUTATAPI &= ~ATAPI_RESET_;
   EZUSB_Delay(100);
   OUTATAPI |= ATAPI_RESET_;

   #if REVC_4611_BOARD
   OEA &= ~ATAPI_RESET_;
   #endif
}   


void initUdmaRead()
{

   FLOWLOGIC = 0x36;
   FLOWEQ0CTL = 0x00;
   FLOWEQ1CTL = 0x02;
   FLOWSTB = 0xD0;
   FLOWSTBEDGE = 0x03;
   GPIFHOLDAMOUNT = 0x01;

   EP8FIFOCFG = bmAUTOIN | bmZEROLENIN | bmWORDWIDE;
   IFCONFIG = 0xc6;
}

void initUdmaWrite()
{   
   WORD byteCount;
   BYTE i;

   // Special code for switching between auto/manual modes.  Make sure that all of
   // the buffers are full before switching.
   for (i = 0, byteCount = 0; i < 4 && byteCount < dataTransferLen; i++, byteCount +=wPacketSize)
   {
      // wait for the sector to show up
      while ((EP2CS & bmEPEMPTY))
         ;

      // commit the buffer(s) to the GPIF
      EP2BCL = 0x00;
      WRITEDELAY();
   }

   FLOWLOGIC = 0x70;
   FLOWEQ0CTL = 0x00;
   FLOWEQ1CTL = 0x08;		// Enable CTL3 signal for XRO
   FLOWSTB = 0x11;
   FLOWSTBEDGE = 0x03;
   if(ActiveLunConfigData.udmaMode == TRANSFER_MODE_UDMA2)
	   FLOWSTBHPERIOD = 0x04;  // for UDMA33
   else  
	   FLOWSTBHPERIOD = 0x02;  // for UDMA66
   GPIFHOLDAMOUNT = 0x01;
   EP2GPIFFLGSEL = 0x01;
   IFCONFIG = 0x86;

   EP2FIFOCFG = bmAUTOOUT | bmWORDWIDE;
}

// Write a single byte to the given disk register or buffer
void writePIO8(char addr, WORD indata)
{

   // make sure GPIF is not busy
    while (!gpifIdle())
        {
        }

   GPIFWFSELECT = 0;    // PIO write is waveform 0

   // Write the address/chip selects
#if COMPACT_FLASH
   if (bCompactFlash)
      OUTATAPI = (addr | (~ATAPI_ADDR_MASK & ATAPI_IDLE_VALUE)) & ~CF_CE1_; // Drive CF_CE low
   else
#endif
      OUTATAPI = (addr | (~ATAPI_ADDR_MASK & ATAPI_IDLE_VALUE));

    // trigger the GPIF
//    if (EP2FIFOCFG & bmWORDWIDE)
      XGPIFSGLDATH = MSB(indata);                       // Single bus transaction on the GPIF
    XGPIFSGLDATLX = LSB(indata);                   // Single bus transaction on the GPIF

   // make sure GPIF is not busy
    while (!gpifIdle())
        {
        }

    // Clear the address/chip selects
    OUTATAPI = ATAPI_IDLE_VALUE;

}   

// Write the string to the given disk register or buffer
void writePIO16(char addr, WORD count)
{
    int timeout = IORDY_TIMEOUT_RELOAD;

    GPIFABORT = 0x00;

    while (!gpifIdle())
      ;

   GPIFWFSELECT = 0;    // PIO write is waveform 0

   // set up GPIF transfer count
   if (EP2FIFOCFG & bmWORDWIDE)
      GPIFTCB1 = MSB(count >> 1);
   else
      GPIFTCB1 = MSB(count);

   // Write the address/chip selects in between here so we don't pay a penalty for syncDelay
#if COMPACT_FLASH
   if (bCompactFlash)
      OUTATAPI = (addr | (~ATAPI_ADDR_MASK & ATAPI_IDLE_VALUE)) & ~CF_CE1_; // Drive CF_CE low
   else
#endif
      OUTATAPI = (addr | (~ATAPI_ADDR_MASK & ATAPI_IDLE_VALUE));

   if (EP2FIFOCFG & bmWORDWIDE)
      GPIFTCB0 = LSB(count >> 1);  // # of GPIF wordwide transactions
   else
      GPIFTCB0 = LSB(count);  // # of GPIF wordwide transactions

   EP2GPIFTRIG = 0x00;           // trigger the transfer
//   GPIFTRIG = 0x00;        // GPIFTRIG[2] = RD/WR BIT (1 = READ)
                              // xxxxxxxx
                              // ||||||00 b0/b1:  EP bit code:  00=EP2, 01=EP4, 10=EP6, 11=EP8
                              // |||||0-- b3:     R/W#: W=0, R=1
                              // 0------- b7:     DONE
    while (!gpifIdle())
      ; 
}   

// Read the status register.  Added to save space.
BYTE readATAPI_STATUS_REG()
{
   return(readPIO8(ATAPI_STATUS_REG));
}

// Read a string from the given disk register or buffer
BYTE readPIO8(char addr)
{
   BYTE retval;

   while (!gpifIdle());

   GPIFWFSELECT = (1 << 4);    // PIO read is waveform 1

   // put out address of interest
#if COMPACT_FLASH
   if (bCompactFlash)
      OUTATAPI = (addr | (~ATAPI_ADDR_MASK & ATAPI_IDLE_VALUE)) & ~CF_CE1_; // Drive CF_CE low
   else
#endif
      OUTATAPI = (addr | (~ATAPI_ADDR_MASK & ATAPI_IDLE_VALUE));

   // trigger the GPIF
   retval = XGPIFSGLDATLX;         // Single bus transaction on the GPIF

   while (!gpifIdle());             // wait till GPIF is done before getting real data

   retval = XGPIFSGLDATLNOX;        // get data from last GPIF transaction
   OUTATAPI = ATAPI_IDLE_VALUE;     // Clear the address/chip selects      

    return(retval);
}

// Read a string from the given disk register or buffer
void readPIO16(char addr, WORD count)
{
   // check for GPIF ready
   while (!gpifIdle());

   GPIFWFSELECT = (1);    // PIO read is waveform 1

   // set up for GPIF transfer - wordwide, so count/2
   if (EP8FIFOCFG & bmWORDWIDE)
      GPIFTCB1 = MSB(count >> 1);     
   else
      GPIFTCB1 = MSB(count);     

   // Write the address/chip selects here so we don't have to call WRITEDELAY();
#if COMPACT_FLASH
   if (bCompactFlash)
      OUTATAPI = (addr | (~ATAPI_ADDR_MASK & ATAPI_IDLE_VALUE)) & ~CF_CE1_; // Drive CF_CE low
   else
#endif
      OUTATAPI = (addr | (~ATAPI_ADDR_MASK & ATAPI_IDLE_VALUE));

   if (EP8FIFOCFG & bmWORDWIDE)
      GPIFTCB0 = LSB(count >> 1);
   else
      GPIFTCB0 = LSB(count);

   // trigger GPIF.  No longer wait 'til done
   GPIFTRIG = 0x07;        // GPIFTRIG[2] = RD/WR BIT (1 = READ)
                           // GPIFTRIG[1..0] = EP#, 00=ep2, 01=ep4, 10 = ep6, 11=ep8

}   

// read count WORDs using UDMA
void readUDMA(DWORD count)
{
   // check for GPIF ready
   while (!gpifIdle());

   GPIFWFSELECT = (3);    // UDMA read is waveform 3

   // Write the address/chip selects -- Note that this is not the same register as the ATAPI_DATA_REG
   OUTATAPI = CS(3) | DA(0) | (~ATAPI_ADDR_MASK & ATAPI_IDLE_VALUE);

   // set up for GPIF transfer - wordwide
   GPIFTCB3 = 0;
   WRITEDELAY();
   GPIFTCB2 = ((BYTE *) &count)[1];
   WRITEDELAY();
   GPIFTCB1 = ((BYTE *) &count)[2];
   WRITEDELAY();
   GPIFTCB0 = LSB(count);

   FLOWSTATE = 0x82;

   // trigger GPIF and wait till done
   GPIFTRIG = 0x07;        // GPIFTRIG[2] = RD/WR BIT (1 = READ)
                           // GPIFTRIG[1..0] = EP#, 00=ep2, 01=ep4, 10 = ep6, 11=ep8

   // Wait for the drive interrupt.  Don't attempt to clear it.  The GPIF is still in use.
   waitForIntrq(0);

   if (!gpifIdle())
   {
      abortGPIF();
   }

   FLOWSTATE = 0x00;
}   

// Wait for all of the bulk buffers to be full (or all of the data to be received)
// Switch to manual mode
// Write count WORDs using UDMA
// Return drive status
void writeUDMA(DWORD count)
{
   BYTE drvstat=0;

   // check for GPIF ready
   while (!gpifIdle());

   GPIFWFSELECT = (2 << 2);    // UDMA write is waveform 2

   // Write the address/chip selects -- Note that this is not the same register as the ATAPI_DATA_REG
   OUTATAPI = CS(3) | DA(0) | (~ATAPI_ADDR_MASK & ATAPI_IDLE_VALUE);

   // set up for GPIF transfer - wordwide
   GPIFTCB3 = 0;
   WRITEDELAY();
   GPIFTCB2 = ((BYTE *) &count)[1];
   WRITEDELAY();
   GPIFTCB1 = ((BYTE *) &count)[2];
   WRITEDELAY();
   GPIFTCB0 = LSB(count);

   FLOWSTATE = 0x83;

   // trigger GPIF and wait till done
   EP2GPIFTRIG = 0;

   // Wait for the drive interrupt.  Don't attempt to clear it.  The GPIF is still in use.
   waitForIntrq(0);

   if (!gpifIdle())
   {
      abortGPIF();
   }

   FLOWSTATE = 0x00;

}   

void abortGPIF()
{
   FLOWSTATE = 0x00;  // xro - take out of UDMA flowstate
   GPIFABORT = 0xff;

   // reset the transaction count state machine,  in FX2 revs up to and
   // including Rev D, there is a bug that prevents the GPIF state machine
   // from properly reseting following an abort.  The following code is a
   // workaround for this problem.  See the FX2 chip errata for details.
}

⌨️ 快捷键说明

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