📄 atareset.c
字号:
while (!gpifIdle()) // wait for the read to complete before continuing
;
OUTATAPI = ATAPI_IDLE_VALUE;
EP6FIFOCFG = saveIt; // re-enable automode if it was set before.
}
void ATAPIIdDevice()
{
bit oldEA;
SendDeviceIdentifyCommand(1);
// The code used to wait here until it saw the DRDY bit (0x40. This bit is obsolete, but still supported by almost all devices.
// However, the TEAC CRN8245 drive will respond with ONLY the ATAPI_STATUS_DRQ_BIT set.
// This was kind of overkill anyway, since the INTRQ line has already indicated that the device is done with the command.
while (!(readATAPI_STATUS_REG() & ATAPI_STATUS_DRQ_BIT))
;
// We need to disable interrupts while using EP6FIFOBUF. Here's why. It is possible
// (even probable) that we could get a USB reset while doing drive identification.
// One of the things that occurs in the USB reset ISR is a reset of the EP6 FIFO.
// It would be bad if that happened just as we were reading drive data into EP6FIFOBUF.
// The following code segment will complete in a deterministic amount of time.
oldEA = EA;
EA = 0;
FetchDeviceIdentifyIntoEp6();
// Add a hack for Takaya CD1016 -- Needs recovery time after ID command
EZUSB_Delay(1);
if (CSMIntrfcDscrOffset)
{
mymemmovexx(CSMSerial, EP6FIFOBUF+ATAPI_INQUIRY_SERIAL, IDE_ID_SERIAL_LEN);
}
#if USE_ATAPI_DEVICE_SERIAL_NUMBER || USE_ATA_DEVICE_SERIAL_NUMBER
if ((bScsi && USE_ATAPI_DEVICE_SERIAL_NUMBER) || (!bScsi && USE_ATA_DEVICE_SERIAL_NUMBER))
{
BYTE xdata *ptr = &halfKBuffer[(BYTE) &SerialNumberStringDscrOffset + 2];
BYTE len = (halfKBuffer[(BYTE) &SerialNumberStringDscrOffset] >> 1) - 1; // Structure len is bytes, we want unicode (words)
BYTE i;
for (i=0;i<len;i++, ptr += 2)
{
BYTE mychar = EP6FIFOBUF[i+ATAPI_INQUIRY_SERIAL];
#if NIBBLE_CONVERT_SERIAL_NUMBER
{
BYTE serialChar = (mychar >> 4) + '0';
if (serialChar > '9')
serialChar += 'A' - '9' - 1;
*ptr = serialChar;
ptr += 2;
i++;
serialChar = (mychar & 0x0F) + '0';
if (serialChar > '9')
serialChar += 'A' - '9' - 1;
*ptr = serialChar;
}
#else
{
*ptr = mychar;
}
#endif
}
}
#endif
// Check for large disk (48 bit) support. ATA-6 spec below....
// 6.2.1
// 4) The contents of words (61:60) and (103:100) shall not be used to determine if 48-bit addressing is
// supported. IDENTIFY DEVICE bit 10 word 83 indicates support for 48-bit addressing.
if (EP6FIFOBUF[IDENTIFY_48BIT_ADDRESSING+1] & (1<<2))
{
bExtAddrSupport = 1;
// This is actually smaller than a loop of 4!!
// Yes, this only supports 0x100 00 00 00 sectors, which is 220,000GB (industry GB, not true)
((BYTE *)&ActiveLunConfigData.driveCapacity)[3] = EP6FIFOBUF[0+IDE_ID_TOTAL_48_BIT_SECTORS_LSW];
((BYTE *)&ActiveLunConfigData.driveCapacity)[2] = EP6FIFOBUF[1+IDE_ID_TOTAL_48_BIT_SECTORS_LSW];
((BYTE *)&ActiveLunConfigData.driveCapacity)[1] = EP6FIFOBUF[2+IDE_ID_TOTAL_48_BIT_SECTORS_LSW];
((BYTE *)&ActiveLunConfigData.driveCapacity)[0] = EP6FIFOBUF[3+IDE_ID_TOTAL_48_BIT_SECTORS_LSW];
}
else
{
bExtAddrSupport = 0;
// This is actually smaller than a loop of 4!!
((BYTE *)&ActiveLunConfigData.driveCapacity)[3] = EP6FIFOBUF[0+IDE_ID_TOTAL_SECTORS_LSW];
((BYTE *)&ActiveLunConfigData.driveCapacity)[2] = EP6FIFOBUF[1+IDE_ID_TOTAL_SECTORS_LSW];
((BYTE *)&ActiveLunConfigData.driveCapacity)[1] = EP6FIFOBUF[2+IDE_ID_TOTAL_SECTORS_LSW];
((BYTE *)&ActiveLunConfigData.driveCapacity)[0] = EP6FIFOBUF[3+IDE_ID_TOTAL_SECTORS_LSW];
}
ActiveLunConfigData.NumCylindersMSB = EP6FIFOBUF[IDENTIFY_NUM_CYLINDERS_MSB];
ActiveLunConfigData.NumCylindersLSB = EP6FIFOBUF[IDENTIFY_NUM_CYLINDERS_LSB];
ActiveLunConfigData.NumHeads = EP6FIFOBUF[IDENTIFY_NUM_HEADS];
ActiveLunConfigData.NumSectPerTrack = EP6FIFOBUF[IDENTIFY_NUM_SECT_PER_TRACK];
// check for PIO3 support (or greater). PIO support is reported in the
// IDENTIFY data from the drive. AND the modes supported by the drive with
// the PIO enables from the configuration eeprom to enable only selected modes.
ActiveLunConfigData.MaxPIO = EP6FIFOBUF[IDENTIFY_ADVANCED_PIO] & PIO_MODES;
ActiveLunConfigData.udmaMode = 0;
// Check for UDMA support. UDMA support is reported in the IDENTIFY data
// from the drive. AND the modes supported by the drive with the UDMA mode
// enables from the configuration eeprom to enable only selected modes.
if (EP6FIFOBUF[IDENTIFY_FIELD_VALIDITY] & bmBIT2)
{
BYTE supportedUdmaModes = 0;
supportedUdmaModes = EP6FIFOBUF[IDENTIFY_UDMA_MODES] & UDMA_MODES;
if (bScsi && !(ATAPI_UDMA_ENABLE))
supportedUdmaModes = 0;
if (!bScsi && !(ATA_UDMA_ENABLE))
supportedUdmaModes = 0;
if (bCompactFlash && !bCF_USES_UDMA)
supportedUdmaModes = 0;
// if (supportedUdmaModes & UDMA_MODE5)
// {
// ActiveLunConfigData.udmaMode = TRANSFER_MODE_UDMA5;
// } else
if (supportedUdmaModes & UDMA_MODE4)
{
ActiveLunConfigData.udmaMode = TRANSFER_MODE_UDMA4;
}
else if (supportedUdmaModes & UDMA_MODE2)
{
ActiveLunConfigData.udmaMode = TRANSFER_MODE_UDMA2;
}
}
// Check for DMA
if (!ActiveLunConfigData.udmaMode)
{
BYTE supportedDmaModes = 0;
supportedDmaModes = EP6FIFOBUF[IDENTIFY_DMA_MODES] & DMA_MODES;
if (bCompactFlash && !bCF_USES_UDMA)
supportedDmaModes = 0;
if (supportedDmaModes & DMA_MODE2)
ActiveLunConfigData.udmaMode = TRANSFER_MODE_DMA2;
}
ActiveLunConfigData.commandSetSupport = EP6FIFOBUF[IDENTIFY_COMMAND_SET_SUPPORT];
// We are done with EP6FIFOBUF. reset the EP6FIFO so the internal pointers are pointing
// back at the start of it and then re-enable interrupts.
FIFORESET = 0x06;
EA = oldEA;
initDriveAfterReset();
ActiveLunConfigData.driveCapacity -= 1; // The command that reads drive capacity actually wants the last valid LBA.
return;
}
void configureATATransferMode(BYTE mode)
{
if (setFeatures(0x3, mode) == USBS_FAILED)
if ((mode & TRANSFER_MODE_UDMA0) || (mode & TRANSFER_MODE_DMA0))
ActiveLunConfigData.udmaMode = DeviceConfigData[currentLunNum].udmaMode = 0;
}
bit setFeatures(BYTE command, BYTE subcommand)
{
// select the drive and set new speed
writeATA_DRIVESEL_REG();
waitForBusyBit();
writePIO8(ATA_SECTOR_COUNT_REG, subcommand);
writePIO8(ATAPI_FEATURE_REG, command); // opcode 0x03 used for transfer mode
writePIO8(ATAPI_COMMAND_REG, ATAPI_COMMAND_SET_FEATURES); // execute the command
return(waitForBusyBit());
}
void ISRINT4() interrupt 10
{
if (!(EP01STAT & bmEP1INBSY))
{
EP1INBUF[0] = IOE >> 2;
EP1INBUF[1] = ((EZUSB_HIGHSPEED()) ? 2 : 0) | VBUSPWRD;
EP1INBC = 2;
}
// Clear the interrupt
EXIF &= ~bmIE4;
}
// Timer ISR -- Cannot be placed with the other ISRs because we want the
// compiler to generate the vector.
void ISRtimer0() interrupt 1
{
if (!hertz61ticks--)
{
seconds--;
hertz61ticks = 61;
};
{
// Check for ATA_ENABLE
// check for tri-state signal on WAKEUP pin. If it's active and we're not tristated,
// reset the CPU
checkATAEnable();
}
if (HIDIntrfcDscrOffset && !(USBCS & bmDISCON))
{
BYTE buttons = (IOE & 0x7f) | ((IOA & 0x8) << 4);
if (oldButtons != buttons)
{
if (!(EP01STAT & bmEP1INBSY))
{
EP1INBUF[0] = buttons;
EP1INBUF[1] = ((EZUSB_HIGHSPEED()) ? 2 : 0) | VBUSPWRD;
EP1INBC = 2;
oldButtons = buttons;
}
}
}
}
void initDriveAfterReset()
{
// If UDMA is supported, enable it. Then, enable the highest PIO mode
// if (bCompactFlash)
// {
//
// }
// else
if (ActiveLunConfigData.udmaMode)
{
configureATATransferMode(ActiveLunConfigData.udmaMode);
}
else
{
// Default waveform is PIO0. Shift up for PIO3 and PIO4
if(ActiveLunConfigData.MaxPIO & PIO4)
{
if (!ActiveLunConfigData.udmaMode)
configureATATransferMode(PIO_MODE4); // SCR_PIO4=0x0C, PIO-mode4
}
else if(ActiveLunConfigData.MaxPIO & PIO3)
{
if (!ActiveLunConfigData.udmaMode)
configureATATransferMode(PIO_MODE3); // SCR_PIO3=0x0B, PIO-mode3
}
}
// enable Advanced Power Management (APM) if supported by the drive and
// specified in the configuration eeprom
if ((ActiveLunConfigData.commandSetSupport & APM_FEATURE) &&
(APM_VALUE))
{
setFeatures(SET_FEATURE_APM_ENABLE, APM_VALUE);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -