Logo GenDocs.ru

Поиск по сайту:  

Загрузка...

Дипломная работа - Мезонинный адаптер USB2.0 - файл Приложение А - код программы.doc


Загрузка...
Дипломная работа - Мезонинный адаптер USB2.0
скачать (2375.9 kb.)

Доступные файлы (43):

1 Оглавление.doc77kb.19.06.2007 05:20скачать
2 Введение.doc27kb.19.06.2007 04:56скачать
3 ТЗ.doc35kb.19.06.2007 04:57скачать
4 Раздел 1 - Специальный.doc1164kb.19.06.2007 04:57скачать
5 Технологическая часть.doc157kb.19.06.2007 05:03скачать
6 Себестоимость.doc123kb.19.06.2007 05:04скачать
7 ПЭБ.doc147kb.19.06.2007 05:06скачать
8 Заключение.doc27kb.19.06.2007 05:07скачать
9 Список используемых источников.doc35kb.19.06.2007 11:19скачать
диплом - что должно быть.txt1kb.21.01.2007 21:10скачать
Книжка дипломника - пустая.doc35kb.13.04.2007 18:32скачать
1.1. Физическая архитектура USB.vsd
1.2. Логическая архитектура USB.vsd
1.3. Кабель USB.vsd
1.8. Отличия между кадрами и микрокадрами.vsd
Спецификация сборочного чертежа.sch
Структурная схема алгоритма программы.vsd
диаграмма.bmp
диаграмма.JPG15kb.12.06.2007 17:22скачать
диаграмма себестоимости.xls17kb.12.06.2007 17:33скачать
рамка VISIO вертикальная.vsd
рамка VISIO горизонтальная.vsd
рамка WORD горизонтальная.doc20kb.04.06.2007 14:19скачать
01 мезонинный адаптер USB.vsd
02 выбор микроконтроллера USB2.0 HS.vsd
03 алгоритм работы программы.vsd
04 алгоритм ПСИ.vsd
05 технологическое оборудование.vsd
06 калькуляция себестоимости.doc53kb.19.06.2007 13:20скачать
01 мезонинный адаптер USB.pdf156kb.19.06.2007 13:22скачать
02 выбор микроконтроллера USB2.0 HS.pdf108kb.19.06.2007 13:22скачать
03 алгоритм работы программы.pdf77kb.19.06.2007 13:16скачать
04 алгоритм ПСИ.pdf70kb.19.06.2007 13:16скачать
05 технологическое оборудование.pdf129kb.19.06.2007 13:18скачать
06 калькуляция себестоимости.pdf124kb.19.06.2007 13:20скачать
топология.pcb
электрическая схема.sch
Приложение А - код программы.doc189kb.19.06.2007 12:32скачать
Приложение Б - ТИ.doc241kb.13.06.2007 13:31скачать
Приложение В - ПЭ3.sch
ТИ Приложение A - схема рабочего места контроля адаптера.vsd
рекомендации по работе над дипломом.doc124kb.02.04.2007 11:17скачать
речь.doc43kb.19.06.2007 20:53скачать

Приложение А - код программы.doc

Реклама MarketGid:
Загрузка...
Приложение А.
В связи с большим объемом кода в приложении представлены наиболее значимые фрагменты программного обеспечения.
fw.c

---------------------------------------------------------------------------------------
#include "fx2.h"

#include "fx2regs.h"

#include "gpif.h"

#include "atapi.h"

#include "globals.h"
//-----------------------------------------------------------------------------

// Constants

//-----------------------------------------------------------------------------

#define DELAY_COUNT 0x9248*8L // Delay for 8 sec at 24Mhz, 4 sec at 48

// USB constants

// Class specific setup commands

#define SC_BOMS_RESET (0x21) // Hard/soft depends on wValue field 0 = hard
//-----------------------------------------------------------------------------

// Prototypes

//-----------------------------------------------------------------------------

void SetupCommand(void);

void TD_Init(void);

void TD_Poll(void);

void DisconAndWaitForVbus();


//-----------------------------------------------------------------------------

// Code

//-----------------------------------------------------------------------------
// Task dispatcher
void main(void) {

BYTE j;

abortGPIF(); // TPM: Unconditionally abort

TD_Init();
EZUSB_IRQ_ENABLE(); // Enable USB interrupt (INT2)

EZUSB_ENABLE_RSMIRQ(); // Wake-up interrupt
INTSETUP |= (bmAV2EN); // Enable INT 2 autovectoring
USBIE = bmSUDAV | bmSUSP | bmURES | bmHSGRANT; // Enable selected interrupts
Sleep = 0;
resetATAPIDevice();
// keep searching for ATA/ATAPI device until we find at least one

while (!(LunBits[0] || LunBits[1])) {

for (j=deviceCount;j<MAX_LUN;j++) {

// Clearing ActiveLunBits clears the bMasterSlaveBit (i.e. we will search for the master the next time through this loop)

ActiveLunBits = 0;
bMasterSlave = j;

detectSCSIvsATA();

if (bDevicePresent) {

LunBits[deviceCount] = ActiveLunBits;

deviceCount++;

}

}

}

for (j=0;j<deviceCount;j++) {

ActiveLunBits = LunBits[j];

if (bDevicePresent) {

ATAPIIdDevice();

mymemmove((BYTE *)&DeviceConfigData[j],(BYTE *)&ActiveLunConfigData, sizeof(DEVICE_CONFIG_DATA));

LunBits[j] = ActiveLunBits;

}

}
EA = 1; // Enable 8051 interrupts

R0 = 1; // Make sure that the timer ISR runs at once. This will take care of the //ATA_ENABLE line

currentLunNum = 0xff;
if(!(USBCS & bmRENUM)) {

#if BUS_POWERED

CT1 = 2;

#endif

// void EZUSB_Discon(BOOL renum)

USBCS |= (bmDISCON | bmRENUM); // disconnect from USB and set the renumerate bit

EZUSB_Delay(2500); // Wait 2500 ms

USBIRQ = 0xff; // Clear any pending USB interrupt requests. They're for our old life.

EPIRQ = 0xff;

EZUSB_IRQ_CLEAR();

}
#if !VBUS_DETECT

// unconditionally re-connect. If we loaded from eeprom we are

// disconnected and need to connect. If we just renumerated this

// is not necessary but doesn't hurt anything

USBCS &=~bmDISCON;

#endif
CKCON = (CKCON&(~bmSTRETCH)) | FW_STRETCH_VALUE; // Set stretch to 0 (after renumeration)
EP0CS |= bmHSNAK;
// Task Dispatcher

while(TRUE) // Main Loop

{

TD_Poll();

} // End while-forever loop

} //End of MAIN()

gpif.c

---------------------------------------------------------------------------------------
#include <scsi.h>

#include "fx2.h"

#include "fx2regs.h"

#include "gpif.h"

#include "globals.h"
// 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 */ 0x08, 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,

};
void hardwareReset() {

^ OEA |= ATAPI_RESET_BIT;

ATAPI_RESET_ = 0;

EZUSB_Delay(100);

ATAPI_RESET_ = 1;
OEA &= ~ATAPI_RESET_BIT;

}
void initUdmaRead() {
FLOWLOGIC = 0x36;

FLOWEQ1CTL = 0x02;

FLOWSTB = 0xD0;
EP8FIFOCFG = 0x0D;

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;

FLOWEQ1CTL = 0x08; // Enable CTL3 signal for XRO

FLOWSTB = 0x11;

if(ActiveLunConfigData.udmaMode == TRANSFER_MODE_UDMA2)

FLOWSTBHPERIOD = 0x04; // for UDMA33

else

FLOWSTBHPERIOD = 0x02; // for UDMA66

EP2GPIFFLGSEL = 0x01;

IFCONFIG = 0x86;
EP2FIFOCFG = bmAUTOOUT | bmWORDWIDE;

}
// 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()) {

}
GPIFWFSELECT = 0; // PIO write is waveform 0
// 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;

}
// Write the string to the data register

void writePIO16(WORD count)

{

int timeout = IORDY_TIMEOUT_RELOAD;
while (!gpifIdle())

;
GPIFWFSELECT = 0; // 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=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 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());
GPIFWFSELECT = (1 << 4); // PIO read is waveform 1
// 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 = (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 = 0x07; // 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 = (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()

{

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.

WAIT_FOR_INTRQ();
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() {

BYTE drvstat=0;
FLOWSTATE = 0x83;
// trigger GPIF and wait till done

^ EP2GPIFTRIG = 0;
// Wait for the drive interrupt.

// Wait for the drive interrupt.

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.

}
ide.c

---------------------------------------------------------------------------------------

//-----------------------------------------------------------------------------

// Copyright (c) 1999 Cypress Semiconductor, Inc. All rights reserved

//-----------------------------------------------------------------------------

//

// This file contains the IDE specific portions of the code. In ATAPI

// or SCSI applications, this file should not be needed.

//

// $Archive: /USB/atapifx2/source_at2Plus_based/ide.c $

// $Date: 7/16/03 4:39p $

// $Revision: 11 $

//-----------------------------------------------------------------------------

#include "Fx2.h"

#include "Fx2regs.h"

#include "gpif.h"

#include "scsi.h"

#include "globals.h"
static bit ideReadCommand(BYTE command);

static bit ideWriteCommand(BYTE command);

bit ideUdmaWriteCommand();

static void IDEnop();

static DWORD dwLBA; // This is global to help the optimizer

WORD stuffLBAandSector(bit readWrite); // Stuff the LBA registers, returns sectorCount

static void IDEPrepareForXfer();

static void loadEP8BC(WORD dataLen);

void EP8Manual();

BYTE loadSensePtrFromErrorRegister(bit readWrite);
// From SCSI spec SPC (SCSI primary commands)

// Byte 0 -- 70 = Current error

// Byte 1 -- Segment number

// Byte 2 -- Sense key (SPC table 107)

// 5 = ILLEGAL REQUEST. Indicates that there was an illegal parameter in the CDB or in the additional parameters supplied as data for some commands

// B = ABORTED COMMAND. Indicates that the device server aborted the command. The application client may be able to recover by trying the command again.

// E = MISCOMPARE. Indicates that the source data did not match the data read from the medium.

// Byte 3-6 -- Information (not used)

// Byte 7 -- add'l sense length

// byte 8-11 -- Command specific information

// byte 12 -- ASC (Add'l sense code)

// byte 13 -- ASQ (Add'l sense qualifier)
const char code senseArray[senseWriteProtected+1][3] =

{{0x0b, 0x08, 0x03}, // senseCRCError 0 // Set on CRC error. Causes host to retry

{0x05, 0x24, 0x00}, // senseInvalidFieldInCDB 1// 300 calls this InvalidCommandField

{0x00, 0x00, 0x00}, // senseOk 2

{0x02, 0x3a, 0x00}, // senseNoMedia 3

{0x03, 0x03, 0x00}, // senseWriteFault 4

{0x03, 0x11, 0x00}, // senseReadError 5

{0x03, 0x12, 0x00}, // senseAddrNotFound 6

{0x05, 0x20, 0x00}, // senseInvalidOpcode 7

{0x05, 0x21, 0x00}, // senseInvalidLBA 8

{0x05, 0x26, 0x00}, // senseInvalidParameter 9

{0x05, 0x53, 0x02}, // senseCantEject 0xa

{0x06, 0x28, 0x00}, // senseMediaChanged 0xb

{0x06, 0x29, 0x00}, // senseDeviceReset 0xc// Initial value. Set in ATARESET.c

{0x07, 0x27, 0x00}}; // senseWriteProtected 0xd
char sensePtr;
/////////////////////////////////////////////////////////////////////////////////

#if DEVICE_TYPE_IS_IDE

/////////////////////////////////////////////////////////////////////////////////


bit generalIDEInCommand() {

BYTE cmd;

bShortPacketSent = 0;

cmd = EP2FIFOBUF[0xf];

switch (cmd) {

// Minimum processing for a case in this switch statement:

case INQUIRY:

{

BYTE i;

// relinquish control of the bulk buffer occupied by the CBW

EP2BCL = 0x80;
waitForInBuffer();
SendDeviceIdentifyCommand();
// No need to disable interrupts here because we are expected to own EP8 at this point.

FetchDeviceIdentifyIntoEp8();

// copy the IDENTIFY data into the top of EP8FIFOBUF

mymemmovexx(EP8FIFOBUF+256, EP8FIFOBUF, 256);

// clear out the bottom of EP8FIFOBUF. This is where we are going to build

// the response to the IDENTIFY command.

^ AUTOPTRL2 = LSB(EP8FIFOBUF);

for (i = SCSI_IDENTIFY_LEN; i; i--)

XAUTODAT2 = 0;

// Place the fields that we need into the SCSI block

AUTOPTRL2 = LSB(EP8FIFOBUF+SCSI_INQUIRY_MANUFACTURER);

for (i = 0; i < SCSI_INQUIRY_MANUFACTURER_LEN; i++) {

// swap bytes within words. This is stored backwards!

^ XAUTODAT2 = EP8FIFOBUF[(ATAPI_INQUIRY_MANUFACTURER * 2 + (i ^ 1)) + 256];

}

XAUTODAT2 = '0';

XAUTODAT2 = EP8FIFOBUF[(ATAPI_INQUIRY_REVISION * 2) + 256]+'0';

XAUTODAT2 = '0';

XAUTODAT2 = EP8FIFOBUF[(ATAPI_INQUIRY_REVISION * 2 +2) + 256]+'0';

EP8FIFOBUF[SCSI_INQUIRY_REMOVABLE_BYTE] |= SCSI_INQUIRY_REMOVABLE_BIT & EP8FIFOBUF[(ATAPI_INQUIRY_REMOVABLE_BYTE) + 256];


EP8FIFOBUF[SCSI_INQUIRY_REVISION_LEN] = 0x1F;

loadEP8BC(SCSI_IDENTIFY_LEN);

sensePtr = senseOk;

return(USBS_PASSED);

}

case READ_06:

case READ_10:

case VERIFY_10: {

sensePtr = senseOk;

checkForMedia(1);
if (sensePtr == senseOk) {

return(ideReadCommand(cmd));

}

else {

// relinquish control of the bulk buffer occupied by the CBW

EP2BCL = 0x80;

failedIn();

return(USBS_FAILED);

}

}

case SEEK_10: {

sensePtr = senseOk;

checkForMedia(1);
if (sensePtr == senseOk) {

// Cannot just call readcommand because it aborts on no dataTransferLen.

IDEPrepareForXfer();

stuffLBAandSector(1);

writePIO8(ATAPI_COMMAND_REG, ATA_COMMAND_SEEK);
if(waitForBusyBit() == USBS_FAILED) {

loadSensePtrFromErrorRegister(1);

return(USBS_FAILED);

}

else

return(USBS_PASSED);

}

else {

// relinquish control of the bulk buffer occupied by the CBW

EP2BCL = 0x80;
failedIn();

return(USBS_FAILED);

}

}
case READ_FORMAT_CAPACITIES:

case READ_CAPACITY: {

BYTE num_bytes = 8;
// relinquish control of the bulk buffer occupied by the CBW

EP2BCL = 0x80;

sensePtr = senseOk;

checkForMedia(1);

waitForInBuffer();

if (sensePtr == senseOk) {

^ AUTOPTRL2 = LSB(EP8FIFOBUF);

if(cmd == READ_FORMAT_CAPACITIES) // add 4 byte capacity list header

{

XAUTODAT2 = 0x0;

XAUTODAT2 = 0x0;

XAUTODAT2 = 0x0;

XAUTODAT2 = 0x08;

num_bytes = 12;

}

XAUTODAT2 = ((BYTE *) &ActiveLunConfigData.driveCapacity)[0];

XAUTODAT2 = ((BYTE *) &ActiveLunConfigData.driveCapacity)[1];

XAUTODAT2 = ((BYTE *) &ActiveLunConfigData.driveCapacity)[2];

XAUTODAT2 = ((BYTE *) &ActiveLunConfigData.driveCapacity)[3];

if(cmd == READ_FORMAT_CAPACITIES)

XAUTODAT2 = ((ATA_SECTOR_SIZE >> 24) & 0xff) | 2; // Report media type -- Formatted

else

XAUTODAT2 = (ATA_SECTOR_SIZE >> 24) & 0xff;

XAUTODAT2 = (ATA_SECTOR_SIZE >> 16) & 0xff;

XAUTODAT2 = (ATA_SECTOR_SIZE >> 8) & 0xff;

XAUTODAT2 = (ATA_SECTOR_SIZE >> 0) & 0xff;
loadEP8BC(num_bytes);

return(USBS_PASSED);

}

else {

failedIn();

return(USBS_FAILED);

}

}
///////////////////////////////////////////////////////////

// Spoofed commands

case MODE_SELECT_06: // Note that these are in BOTH the read and write areas in case they are sent with no data

case MODE_SELECT_10:

{

// relinquish control of the bulk buffer occupied by the CBW

EP2BCL = 0x80;

// This command is allowed to have data.

sensePtr = senseOk;

checkForMedia(1);

if (sensePtr == senseOk)

return(USBS_PASSED);

else

return(USBS_FAILED);

}
case TEST_UNIT_READY:

case FORMAT_UNIT: {

// relinquish control of the bulk buffer occupied by the CBW

EP2BCL = 0x80;

if (dataTransferLen) // This command shouldn't have any data!

failedIn();

sensePtr = senseOk;

checkForMedia(1);

if (sensePtr == senseOk)

return(USBS_PASSED);

else

return(USBS_FAILED);

}

case REQUEST_SENSE: {

// relinquish control of the bulk buffer occupied by the CBW

EP2BCL = 0x80;

waitForInBuffer();
^ AUTOPTRL2 = LSB(EP8FIFOBUF);
// First two bytes are 0x70 and 0x00

XAUTODAT2 = 0x70;

XAUTODAT2 = 0x00;

// Clear the rest of the buffer

mymemmovexx(EP8FIFOBUF+2, EP8FIFOBUF+1, 18-2);

XAUTODAT2 = senseArray[sensePtr][0];
AUTOPTRL2 = 7;

XAUTODAT2 = 18-8; // Length of data following this byte
^ AUTOPTRL2 = 12;

XAUTODAT2 = senseArray[sensePtr][1];

XAUTODAT2 = senseArray[sensePtr][2];
loadEP8BC(18);

sensePtr = senseOk;

return(USBS_PASSED);

}

case STOP_START_UNIT:

case PREVENT_ALLOW_MEDIUM_REMOVAL: {

BYTE options;
options = EP2FIFOBUF[CBW_DATA_START+4];

// relinquish control of the bulk buffer occupied by the CBW

EP2BCL = 0x80;

if (dataTransferLen) // This command shouldn't have any data!

failedIn();
writeATA_DRIVESEL_REG();

sensePtr = senseOk;

checkForMedia(1);

if (sensePtr != senseOk)

return(USBS_FAILED);
waitForBusyBit();

if (cmd == PREVENT_ALLOW_MEDIUM_REMOVAL) {

if (options & 1)

writePIO8(ATA_COMMAND_REG, ATA_COMMAND_MEDIA_LOCK);

else

writePIO8(ATA_COMMAND_REG, ATA_COMMAND_MEDIA_UNLOCK);

}

else // STOP_START_UNIT:

if ((options & 3) == 2) {

writePIO8(ATA_COMMAND_REG, ATA_COMMAND_MEDIA_EJECT);

}
waitForBusyBit();
if (readATAPI_STATUS_REG() & ATAPI_STATUS_ERROR_BIT)

{

BYTE error = loadSensePtrFromErrorRegister(1);

if (error & 4) // command not supported -- Non removable media, return PASS

{

sensePtr = senseOk;

return(USBS_PASSED);

}

else if ((error & 2) && (options & 3) == 2)

sensePtr = senseCantEject;

return(USBS_FAILED);

}

else

return(USBS_PASSED);

break;

}
case MODE_SENSE_06:

case MODE_SENSE_10:

{

BYTE pagenum;

pagenum = EP2FIFOBUF[CBW_DATA_START+2] & 0x3F; // identify page (see p.141 SCSI 2ed.)

EP2BCL = 0x80; // relinquish control of the bulk buffer occupied by the CBW

waitForInBuffer();

if((pagenum != 0x05) && (pagenum != 0x3F)

&& (pagenum != 0x01) && (pagenum != 0x08) && (pagenum != 0x1B))

{ // only respond to requests for certain pages (the mandatory ones plus page 5)

sensePtr = senseInvalidFieldInCDB;

failedIn();

return(USBS_FAILED);

}

// If one of the supported pages is requested, return the 8 byte Mode Parameter Header

// plus a single 12 byte page. Only the Mode Data length (LSB) is significant in the

// Mode Parameter Header. It has a Vendor Specific Medium Type Code in byte 2, and

// a 1 bit WP Write Protect bit in byte 3 that are not initialized here.

// Pages 0x01, and 0x08 do not have significant data - they are spoofed.

// Page 0x1B has a TLUN field in byte 3 that is initialized to 1 (as per ISD).

// Page 0x05 does contain information that is needed to boot to HDD and CDROM.

// Page 0x3F, All Pages, is also responded to.

// The supported pages are (see INF-8070_1_3.pdf p37 Table 25):

// case 0x01: // Read-Write Error Recovery Page

// case 0x08: // Caching Page

// case 0x05: // Flexible Disk Page: needed to boot from USB

// case 0x1B: // Removable Block Access Capabilities Page

// case 0x3F: // All (4) Pages

// The format used is:

// Mode parameter header (4 or 8 bytes)

// Block descriptors (not supported)

// Mode page

EP8FIFOBUF[0] = 0x00;

mymemmovexx(EP8FIFOBUF+1, EP8FIFOBUF, 100-1); // clear buffer - <100 bytes in all responses
^ AUTOPTRL2 = LSB(EP8FIFOBUF);

if (cmd == MODE_SENSE_10)

{

XAUTODAT2 = MSB(0);

if (pagenum == 0x3f)

XAUTODAT2 = LSB(8-2 + 12*4); // return 12 bytes for each page

else

XAUTODAT2 = LSB(8-2 + 12*1); // return 12 bytes for each page

AUTOPTRL2 = LSB(EP8FIFOBUF) + 8; // The rest of the header is zeroes. Start the pages at byte 8.

}

else

{

if (pagenum == 0x3f)

XAUTODAT2 = LSB(4-1 + 12*4); // Header is 4 bytes long, data from each page is 12 bytes.

else

^ XAUTODAT2 = LSB(4-1 + 12*1);

AUTOPTRL2 = LSB(EP8FIFOBUF) + 4;

}
if((pagenum == 0x05) || (pagenum == 0x3F))

{

XAUTODAT2 = 5; // fill out the page num - fields are all 0x0

XAUTODAT2 = 12-2; // set individual Page Length -- return 12 for all commands
if(EZUSB_HIGHSPEED())

{

XAUTODAT2 = 0xFF; // HS Transfer Rate (MSB) (field limited to 65Mb/Sec)

XAUTODAT2 = 0xFF; // HS Transfer Rate (LSB)

}

else

{

XAUTODAT2 = 0x2E; // FS Transfer Rate (MSB) (12Mb/Sec)

XAUTODAT2 = 0xE0; // FS Transfer Rate (LSB)

}

XAUTODAT2 = ActiveLunConfigData.NumHeads; // #Heads

XAUTODAT2 = ActiveLunConfigData.NumSectPerTrack; // #SectorsPerTrack

XAUTODAT2 = (ATA_SECTOR_SIZE >> 8) & 0xff; // Data Bytes per sector (truncated)

XAUTODAT2 = (ATA_SECTOR_SIZE >> 0) & 0xff; // Data Bytes per sector

XAUTODAT2 = ActiveLunConfigData.NumCylindersMSB; // #Cyl MSB

XAUTODAT2 = ActiveLunConfigData.NumCylindersLSB; // #Cyl LSB

^ XAUTODAT2 = 0;

XAUTODAT2 = 0;

}

if(pagenum == 0x1B || pagenum == 0x3f)

{

XAUTODAT2 = 0x1b; // fill out the page num

XAUTODAT2 = 12-2; // set individual Page Length -- return 12 for all commands

XAUTODAT2 = 0;

XAUTODAT2 = 0x01; // set TLUN = 1 for page 0x1B

AUTOPTRL2 += 8; // 8 zeroes too.

}

if(pagenum == 0x1 || pagenum == 0x3f)

{

XAUTODAT2 = 0x1; // fill out the page num

XAUTODAT2 = 12-2; // set individual Page Length -- return 12 for all commands

AUTOPTRL2 += 10; // 10 zeroes too.

}
if(pagenum == 0x8 || pagenum == 0x3f)

{

XAUTODAT2 = 0x8; // fill out the page num

XAUTODAT2 = 12-2; // set individual Page Length -- return 12 for all commands

AUTOPTRL2 += 10; // 10 zeroes too.

}
loadEP8BC(AUTOPTRL2);

sensePtr = senseOk;

return(USBS_PASSED);

} // end case
default:

{

// relinquish control of the bulk buffer occupied by the CBW

EP2BCL = 0x80;

sensePtr = senseInvalidOpcode;

failedIn();

return(USBS_FAILED);

}

}

}
bit generalIDEOutCommand()

{

BYTE cmd;

cmd = EP2FIFOBUF[0xf];

switch (cmd)

{

case WRITE_06:

case WRITE_10:

case WRITE_AND_VERIFY_10:

{

sensePtr = senseOk;

checkForMedia(1);

if (sensePtr == senseOk)

{

return(ideWriteCommand(cmd));

}

else

{

// relinquish control of the bulk buffer occupied by the CBW

EP2BCL = 0x80;

if (dataTransferLen)

stallEP2OUT();
return(USBS_FAILED);

}

}

///////////////////////////////////////////////////////////

// Spoofed commands

case MODE_SELECT_06: // Note that these are in BOTH the read and write areas in case they are sent with no data

// Add kludge for Mac Jaguar OS. Wait for extra OUT packets to show up so we process them properly.

EZUSB_Delay(5);

case MODE_SELECT_10:

{

bit bShortPacketReceived = 0;
// relinquish control of the bulk buffer occupied by the CBW

EP2BCL = 0x80;

// Toss away all of the data received with the command

while (dataTransferLen && !bShortPacketReceived)

{

if(!(EP2CS & bmEPEMPTY))

{

dataTransferLen -= min(EP2BC, dataTransferLen);

if (EP2BC != wPacketSize)

bShortPacketReceived = 1;

EP2BCL = 0x80;

}

}

// This command is allowed to have data.

sensePtr = senseOk;

checkForMedia(1);

if (sensePtr == senseOk)

return(USBS_PASSED);

else

return(USBS_FAILED);

}

default:

// relinquish control of the bulk buffer occupied by the CBW

EP2BCL = 0x80;

if (dataTransferLen)

stallEP2OUT();

sensePtr = senseInvalidOpcode;

return(USBS_FAILED);

break;

}

}

void waitForInBuffer()

{

while((EP8CS & bmEPFULL)); // Wait for an available buffer from the host
return;

}


static bit ideReadCommand(BYTE command)

{

BYTE driveStatus;

WORD sectorcount;

BYTE i;

WORD wordCtr;
if (command == VERIFY_10)

{

// Stuff dataTranferLen with 00 (sector count << 1) 00

dataTransferLenLSB = 0;

dataTransferLen23W = ((EP2FIFOBUF[CBW_DATA_START+7] << (8+1)) + EP2FIFOBUF[CBW_DATA_START+8]) << 1;

dataTransferLenMSB = 0;

}
mymemmoveix(prevCmd,&EP2FIFOBUF[0x0F],10); //mdnspd

prevDataTransferLen = dataTransferLen;
switch (command)

{

case READ_06:

{

((BYTE *) &dwLBA)[0] = 0;

((BYTE *) &dwLBA)[1] = EP2FIFOBUF[CBW_DATA_START+1] & 0x1f;

((BYTE *) &dwLBA)[2] = EP2FIFOBUF[CBW_DATA_START+2];

((BYTE *) &dwLBA)[3] = EP2FIFOBUF[CBW_DATA_START+3];

// relinquish control of the bulk buffer occupied by the CBW

EP2BCL = 0x80;

break;

}

default:

IDEPrepareForXfer();

}
// This loop breaks up the 32 bit length into 8 bits * sectors.

// For example, a read of 0x10000 turns into 0x80 sectors.

while (dataTransferLen)

{

sectorcount = stuffLBAandSector(1);

if (!ActiveLunConfigData.udmaMode || (command == VERIFY_10) || (dataTransferLenLSW & 0x1ff) // UDMA cannot handle sub-sector sized reads

#if COMPACT_FLASH

|| !CF_DETECT_

#endif

)

{

// Execute the read command

if (bExtAddrSupport)

{

if ((command == VERIFY_10))

writePIO8(ATA_COMMAND_REG, ATA_COMMAND_VERIFY_10_EXT);

else

writePIO8(ATA_COMMAND_REG, ATA_COMMAND_READ_10_EXT);

}

else

{

if ((command == VERIFY_10))

writePIO8(ATA_COMMAND_REG, ATA_COMMAND_VERIFY_10);

else

writePIO8(ATA_COMMAND_REG, ATA_COMMAND_READ_10);

}


// The verify command reads from the drive, but doesn't transfer data

// to us.

if ((command == VERIFY_10))

{

if(waitForBusyBit() == USBS_FAILED)

{

loadSensePtrFromErrorRegister(1);

dataTransferLen = 0; // This command has no data but this loop uses dataTransferLen as a counter.

return(USBS_FAILED);

}

else

{

if (sectorcount == 0x100)

dataTransferLenMSW -= 2;

else

dataTransferLen = 0;

continue;

}

}
// Wait for drive non-busy before starting xfer

while (readATAPI_ALT_STATUS_REG() & ATAPI_STATUS_BUSY_BIT)

;

// set up for GPIF transfer - wordwide

//EP8GPIFTCH = MSB(wPacketSize >> 1);

//EP8GPIFTCL = LSB(wPacketSize >> 1);

while (sectorcount--)

{

// Wait for the drive to be non-busy and have either data or an error

while (1)

{

driveStatus = readATAPI_STATUS_REG();

if ((driveStatus & (ATAPI_STATUS_BUSY_BIT | ATAPI_STATUS_DRQ_BIT)) == ATAPI_STATUS_DRQ_BIT)

break;

if ((driveStatus & (ATAPI_STATUS_BUSY_BIT | ATAPI_STATUS_ERROR_BIT)) == ATAPI_STATUS_ERROR_BIT)

break;

}
// If there's an error, the drive may still want to send us the data.

if (driveStatus & ATAPI_STATUS_ERROR_BIT)

{

loadSensePtrFromErrorRegister(1);

if (driveStatus & ATAPI_STATUS_DRQ_BIT)

for (wordCtr = 0; wordCtr < 0x100; wordCtr++)

readPIO8(ATAPI_DATA_REG);

failedIn();

return(USBS_FAILED);

}

else

{

BYTE bLimit;

WORD wThisPacketSize;
if (wPacketSize == 0x40)

bLimit = 8;

else

bLimit = 1;

for (i = 0; i < bLimit && dataTransferLen; i++)

{

waitForInBuffer();
wThisPacketSize = min(wPacketSize, dataTransferLen);

readPIO16(wThisPacketSize);

while (!gpifIdle()) // Wait for xfer to complete

;

EP8BCH = MSB(wThisPacketSize);

EP8BCL = LSB(wThisPacketSize);

dataTransferLen -= wThisPacketSize;

}

// Check for residue at the drive. If it's there, read it all.

if (i < bLimit || wThisPacketSize != wPacketSize)

{

while (readATAPI_STATUS_REG() & ATAPI_STATUS_DRQ_BIT)

readPIO8(ATAPI_DATA_REG);

// Now we have up to 511 bytes of crap in the FIFO.

// Wait for the IN endpoint to be empty, then reset the FIFO

while (!(EP8CS & bmEPEMPTY))

;

^ FIFORESET = 8;

}

}

}//while (sectorcount--)

}

else // transfer is udma mode

{

initUdmaRead();

if (bExtAddrSupport)

writePIO8(ATAPI_COMMAND_REG, ATA_COMMAND_DMAREAD_RETRY_EXT);

else

writePIO8(ATAPI_COMMAND_REG, ATA_COMMAND_DMAREAD_RETRY);

prepUDMA(MSB(sectorcount),LSB(sectorcount),0); // (DWORD) sectorcount << 8

readUDMA(); // Words = sectors * 256
// switch the EP back to manual mode

EP8FIFOCFG = 0x05;

WRITEDELAY();

^ IFCONFIG = IFCONFIG_DEFAULT;
// If there's anything left in the count regs, we've got a problem.

// We will have to STALL in the IN endpoint to stop the host.

// This is the Hi > Di case.

if (GPIFTCMSW || GPIFTCLSW)

{

if ((GPIFTCLSW & 0xff)) // Check for short packet already sent

bShortPacketSent = 1;

failedIn();

attemptFastRead = 0;

}
if (waitForBusyBit() == USBS_FAILED)

{

loadSensePtrFromErrorRegister(1);

if (sensePtr == senseCRCError)

slowDownOnUDMAErrors();

// No need to do failedIn() -- Already checked above to see that all data has been xferred.

return(USBS_FAILED);

}
if (udmaErrorCount)

udmaErrorCount--;
// Two choices -- Either we're limited to 0x100 sectors, or limited to dataTransferLen.

// BUGBUG -- No capability here to report Hi > Di.

attemptFastRead = 1;

if (sectorcount == 0x100)

dataTransferLenMSW -= 2;

else

{

dataTransferLen = 0;

}

}

}//while (dataTransferLen)

return(USBS_PASSED);

}
static bit ideWriteCommand(BYTE command)

{

WORD savebc;

BYTE driveStatus = 0;

WORD sectorcount;

BYTE i;

if (command != WRITE_06)

IDEPrepareForXfer();

else

{

((BYTE *) &dwLBA)[0] = 0;

((BYTE *) &dwLBA)[1] = EP2FIFOBUF[CBW_DATA_START+1] & 0x1f;

((BYTE *) &dwLBA)[2] = EP2FIFOBUF[CBW_DATA_START+2];

((BYTE *) &dwLBA)[3] = EP2FIFOBUF[CBW_DATA_START+3];
// relinquish control of the bulk buffer occupied by the CBW

EP2BCL = 0x80;

}
// If there's no valid data length, just exit once we've freed the CBW buffer

if (dataTransferLen < ATA_SECTOR_SIZE)

return USBS_PASSED;
// If we're going to do DMA, set up the FIFO ONE time before we start

// It's safe to init while a transfer is taking place, but risky to switch back to manual mode

// during a transfer.
if (ActiveLunConfigData.udmaMode && !(dataTransferLenLSW & 0x1ff)

#if COMPACT_FLASH

&& CF_DETECT_

#endif

)

initUdmaWrite();
// Send the command to the drive

// This loop breaks up the 32 bit length into 8 bits * sectors.

// For example, a read of 0x10000 turns into 0x80 sectors.

while (dataTransferLen >= ATA_SECTOR_SIZE)

{

sectorcount = stuffLBAandSector(0);

if (ActiveLunConfigData.udmaMode && !(dataTransferLenLSW & 0x1ff)

#if COMPACT_FLASH

&& CF_DETECT_

#endif

)

{

// Wait for drive non-busy before starting xfer

while (readATAPI_ALT_STATUS_REG() & ATAPI_STATUS_BUSY_BIT)

;
// Execute the write command

if (bExtAddrSupport)

writePIO8(ATA_COMMAND_REG, ATA_COMMAND_DMAWRITE_RETRY_EXT);

else

writePIO8(ATA_COMMAND_REG, ATA_COMMAND_DMAWRITE_RETRY);

if (sectorcount == 0x100)

prepUDMA(0x1,00,00); // 64k Transfers = 128K

else

prepUDMA(MSB(sectorcount),LSB(sectorcount),0);

writeUDMA();
if ((GPIFTCMSW || GPIFTCLSW))

{

stallEP2OUT();

}

// Check status to clear interrupt.

if (readATAPI_STATUS_REG() & ATAPI_STATUS_ERROR_BIT)

{

loadSensePtrFromErrorRegister(0);

return(USBS_FAILED);

}

else

{

if (sectorcount == 0x100)

dataTransferLenMSW -= 2;

else

dataTransferLen = 0;

}

}

else

{

if (ActiveLunConfigData.udmaMode)

{

// cancel AUTO OUT mode.

EP2FIFOCFG = bmWORDWIDE;

WRITEDELAY();

^ IFCONFIG = IFCONFIG_DEFAULT;

}

// Execute the write command

if (bExtAddrSupport)

writePIO8(ATA_COMMAND_REG, ATA_COMMAND_WRITE_10_EXT);

else

writePIO8(ATA_COMMAND_REG, ATA_COMMAND_WRITE_10);

while (sectorcount--)

{

BYTE limit;

// Wait for the drive to be non-busy and have either data or an error

while (1)

{

driveStatus = readATAPI_STATUS_REG();

if ((driveStatus & (ATAPI_STATUS_BUSY_BIT | ATAPI_STATUS_DRQ_BIT)) == ATAPI_STATUS_DRQ_BIT)

break;

if ((driveStatus & (ATAPI_STATUS_BUSY_BIT | ATAPI_STATUS_ERROR_BIT)) == ATAPI_STATUS_ERROR_BIT)

goto stopOnShortPacket;

}

// Normal case -- Got a sector. Send it to the drive (in 8 chunks)

if (wPacketSize == 0x40)

limit = 8;

else

limit = 1;

for (i = 0; i < limit; i++)

{

while(EP2CS & bmEPEMPTY); // Wait for host to send data

savebc = (EP2BCH << 8) | EP2BCL;

// Terminate xfer on receipt of short packet, otherwise drop

// into streamlined case

if (savebc < wPacketSize)

{

EP2BCL = 0;

writePIO16(savebc+1); // Add 1 to allow odd xfers.

// This looks wrong, but i is always 0 when wPacketSize is 0x200.

dataTransferLen -= savebc + i * 0x40; /*wPacketSize*/

goto stopOnShortPacket;

}

else

{

EP2BCL = 0;

writePIO16(wPacketSize);

}

}

dataTransferLen -= ATA_SECTOR_SIZE; // Returned a full sector.

} // while (sectorcount)

} // else (if udma)

} // While (dataTransferLen)

stopOnShortPacket:

// cancel AUTO OUT mode, put IFCLK back to normal

^ IFCONFIG = IFCONFIG_DEFAULT;

if (bCompactFlash)

EP2FIFOCFG = bmZEROLENIN;

else

EP2FIFOCFG = bmZEROLENIN | bmWORDWIDE;
if (driveStatus & ATAPI_STATUS_ERROR_BIT)

{

loadSensePtrFromErrorRegister(0);

return(USBS_FAILED);

}

else

return(USBS_PASSED);

}


/* This command is only used for removable DRIVES, not removable media. An example of removable drive is Compact Flash */

// Check to see if a new CF is inserted. Called before executing every command to make sure

// we have media. Called from TD_Poll to detect status changes between host activity.

// If we're not looking at a CF device, still check for CF but return 1 -- Media here.

//

// Input -- commandProcessing: When set to 0, we will not modify the sensePtr, we will just look for CF changes.
WORD stuffLBAandSector(bit readWrite) // Stuff the LBA registers

{

WORD sectorcount;
writeATA_DRIVESEL_REG();
// First stuff the length register (number of sectors to read)

if (dataTransferLenMSW & 0xfffe)

{

if (bExtAddrSupport)

writePIO8(ATA_SECTOR_COUNT_REG, 1); // if (bExtAddrSupport) we need to stuff the MSB

writePIO8(ATA_SECTOR_COUNT_REG, 0); // 0 means 256 blocks of 512 bytes -- Max drive xfer, max TC

sectorcount = 0x100;

}

else

{

// Round sectorcount up for reads, down for writes

if (readWrite)

sectorcount = (dataTransferLenLSW + ATA_SECTOR_SIZE-1)/ATA_SECTOR_SIZE + (dataTransferLenMSW & 1) * 0x80;

else

sectorcount = (dataTransferLenLSW)/ATA_SECTOR_SIZE + (dataTransferLenMSW & 1) * 0x80;
if (bExtAddrSupport)

writePIO8(ATA_SECTOR_COUNT_REG, 0); // for extended addressing

writePIO8(ATA_SECTOR_COUNT_REG, sectorcount); // divide len into blocks

}
if (bExtAddrSupport)

{

writePIO8(ATA_LBA_LSB_REG, ((BYTE *) &dwLBA)[0]); // LBA (31:24)

writePIO8(ATA_LBA_2SB_REG, 0); // LBA (39:32)

writePIO8(ATA_LBA_MSB_REG, 0); // LBA (47:40)

}
writePIO8(ATA_LBA_LSB_REG, ((BYTE *) &dwLBA)[3]); // LBA (7:0)

writePIO8(ATA_LBA_2SB_REG, ((BYTE *) &dwLBA)[2]); // LBA (15:8)

writePIO8(ATA_LBA_MSB_REG, ((BYTE *) &dwLBA)[1]); // LBA (23:16)
if (!bExtAddrSupport)

{

writePIO8(ATA_DRIVESEL_REG, ((BYTE *) &dwLBA)[0] | 0xe0 | ((BYTE)bMasterSlave << 4));

}
dwLBA += sectorcount;

return sectorcount;

}
void writeATA_DRIVESEL_REG()

{

writePIO8(ATA_DRIVESEL_REG, 0xe0 | ((BYTE)bMasterSlave << 4));

}


static void IDEPrepareForXfer()

{

writeATA_DRIVESEL_REG();

waitForBusyBit();

// Oddly enough, an error bit is okay here. It means that the LAST command failed, not this one.

// A new command is required to clear many error conditions.

((BYTE *) &dwLBA)[0] = EP2FIFOBUF[CBW_DATA_START+2];

((BYTE *) &dwLBA)[1] = EP2FIFOBUF[CBW_DATA_START+3];

((BYTE *) &dwLBA)[2] = EP2FIFOBUF[CBW_DATA_START+4];

((BYTE *) &dwLBA)[3] = EP2FIFOBUF[CBW_DATA_START+5];
// relinquish control of the bulk buffer occupied by the CBW

EP2BCL = 0x80;

}
static BYTE loadSensePtrFromErrorRegister(bit readWrite)

{

BYTE error;
error = readPIO8(ATAPI_ERROR_REG);

if (!error)

sensePtr = senseOk;

else if (error & 0x80) // CRC

sensePtr = senseCRCError;

else if (error & 0x02) // No media present

sensePtr = senseNoMedia;

else if (error & 0x20) // Media changed

sensePtr = senseMediaChanged;

else if (error & 0x10) // Addr out of range

sensePtr = senseAddrNotFound;

else if (error & 0x40) // Uncorrectable read error / Write Protect

{

if (readWrite)

sensePtr = senseReadError;

else

sensePtr = senseWriteProtected;

}

else if (error & 0x08) // Media change requested -- No good translation for this one.

sensePtr = senseInvalidOpcode;

else if (error & 0x04) // Command not supported or CRC error or request out of range

{

if (readWrite)

sensePtr = senseReadError;

else

sensePtr = senseWriteFault;

}

else

sensePtr = senseInvalidOpcode;
return(error);

}
void loadEP8BC(WORD dataLen)

{

WORD packetLen;
packetLen = min(dataTransferLen, dataLen);

if (packetLen || (SHORT_PACKET_BEFORE_STALL))

{

EP8BCH = MSB(packetLen);

EP8BCL = LSB(packetLen);

dataTransferLen -= packetLen;

}

if (packetLen & (wPacketSize - 1))

bShortPacketSent = 1;
failedIn(); // This doesn't set status, just STALLs the IN endpoint if needed.

}
void EP8Manual()

{

// switch the EP back to manual mode

EP8FIFOCFG = bmZEROLENIN | bmWORDWIDE;

WRITEDELAY();

^ IFCONFIG = IFCONFIG_DEFAULT;

}

void FastReadStart()

{

// bump the LBA to what we think it will be

// dwLBA += *((WORD *) &prevCmd[7]);
// now put the bumped LBA in our previous CBW buffer for later comparison

*((unsigned long *) &prevCmd[2]) = dwLBA;
// get our saved transfer length from the previous transfer

dataTransferLen = prevDataTransferLen;
gSectorcount = stuffLBAandSector(1);
initUdmaRead();
}
bit FastReadComplete()

{

bit error;
// this is basically from idereadcommand()

while (dataTransferLen)

{

// initUdmaRead();

error = 0;

if (bExtAddrSupport)

writePIO8(ATAPI_COMMAND_REG, ATA_COMMAND_DMAREAD_RETRY_EXT);

else

writePIO8(ATAPI_COMMAND_REG, ATA_COMMAND_DMAREAD_RETRY);

prepUDMA(MSB(gSectorcount),LSB(gSectorcount),0);

readUDMA(); // Words = sectors * 256

// If there's anything left in the count regs, we've got a problem.

// We will have to STALL in the IN endpoint to stop the host.

if (GPIFTCMSW || GPIFTCLSW)

{

if ((GPIFTCLSW & 0xff)) // Check for short packet already sent

bShortPacketSent = 1;

EP8Manual();

failedIn();

error = 1; // Set an error flag here, but don't return yet. Still have to load an error code.

}
if (readATAPI_STATUS_REG() & ATAPI_STATUS_ERROR_BIT)

{

loadSensePtrFromErrorRegister(1);

// No need to do failedIn() -- Already checked above to see that all data has been xferred.

EP8Manual();

return(USBS_FAILED);

}

// If the xfer failed but the drive didn't detect an error, ask the host to retry by setting a CRC error

else if (error)

{

sensePtr = senseCRCError;

EP8Manual();

return(USBS_FAILED);

}

// Two choices -- Either we're limited to 0x100 sectors, or limited to dataTransferLen.

// BUGBUG -- No capability here to report Hi > Di.

if (gSectorcount == 0x100)

{

gSectorcount = stuffLBAandSector(1);

dataTransferLenMSW -= 2;

}

else

dataTransferLen = 0;

}//while (dataTransferLen)
attemptFastRead = 1;

EP8Manual();

return(USBS_PASSED);

}

/////////////////////////////////////////////////////////////////////////////////

#endif // DEVICE_TYPE_IS_IDE

/////////////////////////////////////////////////////////////////////////////////


periph.c

---------------------------------------------------------------------------------------
#pragma NOIV // Do not generate interrupt vectors
#include "fx2.h"

#include "fx2regs.h"

#include "gpif.h"

#include "atapi.h"

#include "globals.h"
extern BOOL Sleep;

extern BOOL Rwuen;

extern BOOL Selfpwr;
void clearResetLine();
//-----------------------------------------------------------------------------

// Task Dispatcher hooks

// The following hooks are called by the task dispatcher.

//-----------------------------------------------------------------------------
void TD_Init(void) // Called once at startup

{

bFirstTime = !TR0;
AUTOPTRSETUP = 0x7;

^ AUTOPTRH2 = MSB(EP8FIFOBUF);
if (bFirstTime) {

mymemmovexx(halfKBuffer, (char xdata *) &DeviceDscr, (WORD)&DscrEndOffset);

}
// init state/reset variables

currentState = UNCONFIGURED;
phaseErrorState = 0;
deviceCount = 0;
LunBits[0] = LunBits[1] = ActiveLunBits = 0; // zeroes out bCompactFlash, bScsi, bExtAddrSupport
attemptFastRead = 0;
initUSB(); // configure output ports and endpoint params

mymemmovexx(&GPIF_WAVE_DATA, (BYTE xdata *) WaveDataPioUDMA, 128); // load wave forms in memory


}
void TD_Poll(void) // Called repeatedly while the device is idle

{

WORD count = 0;
// check EP2 EMPTY(busy) bit in EP2468STAT (SFR), core set's this bit when FIFO is empty

if(!(EP2CS & bmEPEMPTY)) {

// Check for "USBC"

if (checkCBW() == USBS_PASSED)

// Good packet, forward to the device.

processCBW();

else

{

// if we receive an invalid CBW, STALL both bulk endpoints and remain that

// way until reset recovery (MSC BOT 6.6.1)

EP2CS = EP8CS = bmEPSTALL;

phaseErrorState = 1;

}

}
}
//-----------------------------------------------------------------------------

// Support functions for specific device

//-----------------------------------------------------------------------------
void initUSB(void)

{

^ PORTACFG = 0;
OUTATAPI = ATAPI_IDLE_VALUE;
// Make Interrupt 0 level triggered

IT0 = 0;
IFCONFIG = IFCONFIG_DEFAULT;

CPUCS = bmCLKSPD1 | bmCLKINV; // set clock to 48MHz. clock output disabled. inverted.

PINFLAGSCD = 0x00; // FLAGB FF for FIFO selected by FIFOADR[1..0]
// GPIF and CTL configuration

checkATAEnable(); // Sets GPIFIDLECTL, OEA

GPIFIDLECS = 0; // tristate data bus during idle interval

GPIFTCB3 = 0; // Set this ONCE, not every time. No xfers longer than 24 bits.
FLOWEQ0CTL = 0x00; // UDMA init that's the same for both read and write

FLOWSTBEDGE = 0x03; //

GPIFHOLDAMOUNT = 0x01; //


// GPIFWFSELECT = (2 << 6) | (3 << 4) | (0 << 2) | (1); // Single write is 2, Single read is 3, write is 0, Read is waveform 1
// Endpoint initialization

EP2CFG = 0xA0; // ep2 is valid BULK OUT 512 quad buffered

EP2FIFOCFG = 0x05; // WORDWIDE=1M MANUAL

EP2FIFOPFH = 0x00; // PF=0 when BC > PF -> Decis=0 (1 byte in FIFO)

EP2FIFOPFL = 0x00; // PF and BC refer to the current pkt -> PKTSTAT=0
EP8CFG = 0xE0; // ep8 is valid BULK IN 512 double buffered

EP8FIFOCFG = 0x05; // set EP8: 0x05=MANUAL, 0x0D=AUTOIN
EP1OUTCFG = EP1INCFG = EP4CFG = EP6CFG = 0x22;
// disbable Auto Arm

REVCTL = bmNOAUTOARM;
// arm the OUT endpoint. By default OUT endpoints come up unarmed.

ResetAndArmEp2();
// reset the EP8 FIFO. If we are here as the result of a USB reset or MSC

// Reset Recovery, EP8 may need to be cleaned up.

FIFORESET = 0x08;
}

// Stalls EP2OUT endpoint.

void stallEP2OUT()

{

// Check to see if stall is needed. If it is, STALL the endpoint.

// After we have set the STALL, make sure we didn't get the last packet while we were STALLing.

WORD x;
if (EP2468STAT & bmEP2EMPTY)

x = 0;

else

x = EP2FIFOBCL + (EP2FIFOBCH << 8) + EP2BC;
if (dataTransferLen > x) {

EP2CS |= bmEPSTALL;
EZUSB_Delay(100);

if (EP2CS & bmEPSTALL)

x=1234;
if (EP2468STAT & bmEP2EMPTY)

x = 0;

else

x = EP2FIFOBCL + (EP2FIFOBCH << 8) + EP2BC;

if (dataTransferLen > x) {

ResetAndArmEp2(); // Stall no longer needed

EP2CS = 0; // Clear stall bit

}

}

}
// This function pulls common information out of the CBW

void processCBWHeader()

{

currentState = RECEIVED_CBW; // This will prevent us from processing CBWs in the ISR.
// Save the tag for use in the response

cbwTagLow = *((WORD volatile xdata*)(EP2FIFOBUF+CBW_TAG));

cbwTagHi = *((WORD volatile xdata*)(EP2FIFOBUF+CBW_TAG+2));
// Get the length (convert from little endian)

*(((BYTE *) &dataTransferLen)+3) = (EP2FIFOBUF+CBW_DATA_TRANSFER_LEN_LSB)[0]; // "Residue"

*(((BYTE *) &dataTransferLen)+2) = (EP2FIFOBUF+CBW_DATA_TRANSFER_LEN_LSB)[1]; // "Residue"

*(((BYTE *) &dataTransferLen)+1) = (EP2FIFOBUF+CBW_DATA_TRANSFER_LEN_LSB)[2]; // "Residue"

*(((BYTE *) &dataTransferLen)+0) = (EP2FIFOBUF+CBW_DATA_TRANSFER_LEN_LSB)[3]; // "Residue"
directionIn = EP2FIFOBUF[CBW_FLAGS] & 0x80;

}
void processCBW()

{

BYTE CbwLun;
CbwLun = EP2FIFOBUF[CBW_LUN];

if (CbwLun == currentLunNum && attemptFastRead)

{

attemptFastRead = 0;

if (!(mymemcmpa(prevCmd,&EP2FIFOBUF[0x0F],10+1)))

// if (*((DWORD *) &prevCmd[2]) == *((DWORD *) &EP2FIFOBUF[17]))

// if (!(mymemcmp(&prevCmd[4],&EP2FIFOBUF[0x14],2)))

{

BYTE status;
status = FastReadComplete();

// Save the tag for use in the response

cbwTagLow = *((WORD volatile xdata*)(EP2FIFOBUF+CBW_TAG));

cbwTagHi = *((WORD volatile xdata*)(EP2FIFOBUF+CBW_TAG+2));
// relinquish control of the bulk buffer occupied by the CBW

EP2BCL = 0x80;

sendUSBS(status);

currentState = WAIT_FOR_CBW;

return;

}

else

{

// switch the EP back to manual mode

EP8FIFOCFG = bmZEROLENIN | bmWORDWIDE;

WRITEDELAY();

^ IFCONFIG = IFCONFIG_DEFAULT;

}

}

else

attemptFastRead = 0;


processCBWHeader();
if (!(CbwLun == currentLunNum)) {

mymemmove((BYTE *)&ActiveLunConfigData,(BYTE *)&DeviceConfigData[CbwLun], sizeof(DEVICE_CONFIG_DATA));

ActiveLunBits = LunBits[CbwLun];

currentLunNum = CbwLun;
EP2FIFOCFG = EP8FIFOCFG = bmZEROLENIN | bmWORDWIDE; // ATA/ATAPI is word-wide
// We've switched devices. Do we need to switch PIO modes too?

// if (!(DeviceConfigData[0].MaxPIO == DeviceConfigData[1].MaxPIO))

// ALWAYS switch. It's easier than special casing startup.
// switch to PIO4

if(ActiveLunConfigData.MaxPIO & PIO4) {

mymemmovexx(&GPIF_WAVE_DATA, (BYTE xdata *) WaveDataPioUDMA+4, 8 + 4);

mymemmovexx(&(GPIF_WAVE_DATA) + 32, (BYTE xdata *) WaveDataPioUDMA+32+4, 8 + 4);

}

// switch to PIO3

else if(ActiveLunConfigData.MaxPIO & PIO3) {

mymemmovexx(&GPIF_WAVE_DATA, (BYTE xdata *) WaveDataPioUDMA+4, 8 + 4);

mymemmovexx(&(GPIF_WAVE_DATA) + 32, (BYTE xdata *) WaveDataPioUDMA+32+4, 8 + 4);

((BYTE xdata *)&GPIF_WAVE_DATA)[0] = 0x6;

((BYTE xdata *)&GPIF_WAVE_DATA)[32] = 0x6;

}

// switch to PIO0

else {

mymemmovexx(&GPIF_WAVE_DATA, (BYTE xdata *) WaveDataPioUDMA, 8 + 4);

mymemmovexx(&(GPIF_WAVE_DATA) + 32, (BYTE xdata *) WaveDataPioUDMA+32, 8 + 4);

}
}
// Config CB

// Our personal "firmware update" command

if (EP2FIFOBUF[0xf] == 0xfb && !(EP2FIFOBUF[CBW_FLAGS] & CBW_FLAGS_DIR_BIT)) {

// relinquish control of the bulk buffer occupied by the CBW

EP2BCL = 0x80;
// Write the entire EEPROM

EEPROMWrite(dataTransferLenLSW);

sendUSBS(USBS_PASSED);

}
else if (directionIn || !dataTransferLen) {

currentState = RECEIVED_IN_CMD;

if (bScsi)

sendUSBS(generalSCSIInCommand());

else

sendUSBS(generalIDEInCommand());

while (!gpifIdle()); // wait till GPIF is done before getting real data
OUTATAPI = ATAPI_IDLE_VALUE; // Clear ATA control lines. Really only needed to turn off the CF LED.

}

else {

currentState = RECEIVED_OUT_CMD;

if (bScsi)

sendUSBS(generalSCSIOutCommand());

else

sendUSBS(generalIDEOutCommand());

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

OUTATAPI = ATAPI_IDLE_VALUE; // Clear ATA control lines. Really only needed to turn off the CF LED.

}
currentState = WAIT_FOR_CBW;

} //End of ProcessCBW







Скачать файл (2375.9 kb.)

Поиск по сайту:  

© gendocs.ru
При копировании укажите ссылку.
обратиться к администрации
Рейтинг@Mail.ru