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

📄 gpif.c

📁 cy68013a USB2.0 highspeed mass storage source code
💻 C
字号:
//-----------------------------------------------------------------------------
//  Copyright (c) 1999 Cypress Semiconductor, Inc. All rights reserved
//-----------------------------------------------------------------------------
//
// This file contains GPIF support code.  
//
// $Archive: /USB/atapifx2/CY4611B/gpif.c $
// $Date: 4/06/05 10:46a $
// $Revision: 3 $
//-----------------------------------------------------------------------------
//#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+64] =                                                           
{                                                                                          
// 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 (unused)  */       0x07, 0x11, 0x01, 0x3f,
/* LFun  */ 0x00,     0x00,     0x00,     0x36,     /* CF Opcod (unused)  */       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 (unused)  */   0x08, 0x11, 0x04, 0x3f,
/* LFun  */ 0x00,     0x00,     0x00,     0x00,     /* CF Opcod (unused)  */   0x00, 0x01, 0x06, 0x01,
// Wave 0  UDMA Write
/* LenBr */ 0x08,     0x01,     0x06,     0x1C,     0x25,     0x01,     0x02,     0x07,    
/* Opcode*/ 0x01,     0x00,     0x02,     0x03,     0x01,     0x02,     0x26,     0x00,    
/* Output*/ 0xFF,     0xFB,     0xFA,     0xFA,     0xd8,     0xFB,     0xFB,     0xFF,    
/* LFun  */ 0x09,     0x09,     0x12,     0xe9,     0x09,     0x2d,     0x36,     0x3F,     
//            |         |         |         |         |         |         |-- Drive CRC
//            |         |         |         |         |         |-- Assert STOP
//            |         |         |         |         |-- Wait for drive to drop DMARQ.  Float HSTROBE
//            |         |         |         |-- Data transfer state.  Pause on DSTROBE, exit on RDY5 (TC)
//            |         |         |-- Remove STOP
//            |         |-- Assert DMACK
//            |-- Wait for drive to assert DMARQ.  Branch to state 1 on DMARQ.  
// Wave 1  UDMA Read
/* LenBr */ 0x08,     0x01,     0x13,     0x01,     0x25,     0x02,     0x01,     0x07,    
/* Opcode*/ 0x01,     0x00,     0x01,     0x00,     0x01,     0x26,     0x26,     0x00,    
/* Output*/ 0xFF,     0xFB,     0xF8,     0xFB,     0xFB,     0xFB,     0xFF,     0xFF,    
/* LFun  */ 0x09,     0x09,     0xE9,     0x1b,     0x09,     0x2D,     0x36,     0x3F,    
//            |         |         |         |         |         |         |-- Drive CRC.  Done.
//            |         |         |         |         |         |-- Drive CRC
//            |         |         |         |         |-- Wait for drive to drop DMARQ
//            |         |         |         |-- STOP ->1, HSTB->1
//            |         |         |-- Data transfer state.  STOP = 0, HSTB = 0, DMACK = 0.  Exit on DMARQ or RDY5 (TC)
//            |         |-- Assert DMACK
//            |-- Wait for drive to assert DMARQ.  Branch to state 1 on DMARQ.  

// Wave 2 
/* LenBr */ 0x88,     0x8A,     0x03,     0xBC,     0x88,     0x01,     0x01,     0x07,
/* Opcode*/ 0x01,     0x03,     0x02,     0x03,     0x07,     0x02,     0x02,     0x00,
/* Output*/ 0xF7,     0xF2,     0xF2,     0xF3,     0xF3,     0xF3,     0xF3,     0xF7,
/* LFun  */ 0x09,     0x36,     0x00,     0x2D,     0x09,     0x00,     0x00,     0x3F,
// Wave 3 
/* LenBr */ 0x88,     0x8A,     0x03,     0xBC,     0x88,     0x01,     0x01,     0x07,
/* Opcode*/ 0x01,     0x01,     0x00,     0x07,     0x01,     0x00,     0x00,     0x00,
/* Output*/ 0xF7,     0xF1,     0xF1,     0xF3,     0xF3,     0xF3,     0xF3,     0xF7,
/* LFun  */ 0x09,     0x36,     0x00,     0x2D,     0x09,     0x00,     0x00,     0x3F,

};                                                                                         


void hardwareReset()
{
   OEA |= ATAPI_RESET_BIT;    // Needed for revC board.  Doesn't hurt for old pinout.
   ATAPI_RESET_ = 0;
   EZUSB_Delay(100);
   ATAPI_RESET_ = 1;

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


void initUdmaRead()
{
   // Only use flow state for UDMA, not for DMA
   if (ActiveLunConfigData.udmaMode & TRANSFER_MODE_UDMA0)
      {
      FLOWLOGIC = 0x36;
      FLOWEQ1CTL = 0x02;
      FLOWSTB = 0xD0;
      }

   EP6FIFOCFG = 0x0D;      // Turn on AUTO mode
   IFCONFIG = 0xc2;        // Make sure we're using 48Mhz interface clock
   // EP6GPIFFLGSEL = 0;   // Default -- Use programmable flag.
}

void initUdmaWrite()
{   
   // Only use flow state for UDMA, not for DMA
   if (ActiveLunConfigData.udmaMode & TRANSFER_MODE_UDMA0)
      {
      FLOWLOGIC = 0x70;
      FLOWEQ1CTL = 0x08;		// Enable CTL3 signal for debugging
      FLOWSTB = 0x11;
      if(ActiveLunConfigData.udmaMode == TRANSFER_MODE_UDMA2)
   	   FLOWSTBHPERIOD = 0x04;  // for UDMA33
      else  
   	   FLOWSTBHPERIOD = 0x02;  // for UDMA66
      IFCONFIG = 0x82;  // Slow the clock to 30Mhz
      }
   EP2GPIFFLGSEL = 0x01;         // Select empty flag

   FIFORESET = bmNAKALL;             // Set NAKALL bit

   // Wait one packet time -- 50uS at full-speed, 10us at high-speed
   {
   BYTE count;
   BYTE i;

   if (EZUSB_HIGHSPEED())
      count = 10;
   else
      count = 50;
   for (; count; count--)
      i = halfKBuffer[0];      
   }

   // wait for the sector to show up
   // commit the buffer(s) to the GPIF
   while (!(EP2468STAT & bmEP2EMPTY))
      EP2BCL = 0x00;

#if 0
   {
      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 (EP2468STAT & bmEP2EMPTY)
            ;
   
         // commit the buffer(s) to the GPIF
         EP2BCL = 0x00;
         WRITEDELAY();
      }
   }
#endif

   EP2FIFOCFG = bmAUTOOUT | bmWORDWIDE;
   FIFORESET = 0x00;             // Clear NAKALL bit
}

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

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

   // Write the address/chip selects
   OUTATAPI = addr | (~ATAPI_ADDR_MASK & ATAPI_IDLE_VALUE);

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

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

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

#if DEVICE_TYPE_IS_SCSI
// Write a single byte to the given disk register or buffer
void fastWritePIO8(char addr, BYTE indata)
{

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

   // Write the address/chip selects
   OUTATAPI = addr | (~ATAPI_ADDR_MASK & ATAPI_IDLE_VALUE);

    // trigger the GPIF
    XGPIFSGLDATLX = indata;                   // Single bus transaction on the GPIF
}   
#endif
// Write the string to the data register
void writePIO16(WORD count)
{
    int timeout = IORDY_TIMEOUT_RELOAD;

    while (!gpifIdle())
      ;

   GPIFWFSELECT = GPIFWFSELECT_DEFAULT | (0 << 2);    // PIO write is waveform 0

   // set up for GPIF transfer - wordwide, so count/2
      {
      GPIFTCB1 = MSB(count) >> 1;     
      // Write the address/chip selects here so we don't have to call WRITEDELAY();
      OUTATAPI = (ATAPI_DATA_REG | (~ATAPI_ADDR_MASK & ATAPI_IDLE_VALUE));
      GPIFTCB0 = LSB(count >> 1);
      }

   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=EP6
                              // |||||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 the alt status register.  Added to save space.
BYTE readATAPI_ALT_STATUS_REG()
{
   return(readPIO8(ATAPI_ALT_STATUS_REG));
}

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

   while (!gpifIdle());

   // put out address of interest
      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;
    return(retval);
}

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

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

   // set up for GPIF transfer - wordwide, so count/2
      {
      count++;    // add 1 to count in case it's odd.
      GPIFTCB1 = MSB(count) >> 1;     
      // Write the address/chip selects here so we don't have to call WRITEDELAY();
      OUTATAPI = (ATAPI_DATA_REG | (~ATAPI_ADDR_MASK & ATAPI_IDLE_VALUE));
      GPIFTCB0 = LSB(count >> 1);
      }

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

}   

void prepUDMA(BYTE b2, BYTE b1, BYTE b0)
{
   // check for GPIF ready
   while (!gpifIdle());

   GPIFWFSELECT = GPIFWFSELECT_DEFAULT | (2 << 2) | 3;    // UDMA write is waveform 2, 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
   GPIFTCB2 = b2;
   WRITEDELAY();
   GPIFTCB1 = b1;
   WRITEDELAY();
   GPIFTCB0 = b0;
}

// read count WORDs using UDMA
void readUDMA()
{
   bit retval = 0;

   if (ActiveLunConfigData.udmaMode & TRANSFER_MODE_UDMA0)
      FLOWSTATE = 0x82;

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

   // Wait for the drive interrupt or GPIF done
   if (bCOMPLIANCE_MODE)
      {
      #if REVC_4611_BOARD                     
         {
         WAKEUPCS = bmWU | bmWUEN; 
         while((WAKEUPCS & 0x40) && !gpifIdle()) 
            {WAKEUPCS = bmWU | bmWUEN;}
         }
      #else    // AT2LP_PINOUT
         {
         while (!PA0 && !gpifIdle()) 
            ;
         }
      #endif
      }
   else
      WAIT_FOR_INTRQ();

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

   FLOWSTATE = 0x00;
   return;
}   

// 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()
{
   BYTE drvstat=0;

   if (ActiveLunConfigData.udmaMode & TRANSFER_MODE_UDMA0)
      FLOWSTATE = 0x83;

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

   // Wait for the drive interrupt.
   // Wait for the drive interrupt.
   // Wait for the drive interrupt or GPIF done
   if (bCOMPLIANCE_MODE)
      {
      #if REVC_4611_BOARD                     
         {
         WAKEUPCS = bmWU | bmWUEN; 
         while((WAKEUPCS & 0x40) && !gpifIdle()) 
            {WAKEUPCS = bmWU | bmWUEN;}
         }
      #else    // AT2LP_PINOUT
         {
         while (!(IOA & 1) && !gpifIdle()) 
            ; 
         }
      #endif
      }
   else
      WAIT_FOR_INTRQ();

   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 + -