Respond to a few ATAPI commands in the early initialization procedure

Still getting stuck waiting for a DMA read
This commit is contained in:
StrikerX3 2018-12-08 14:33:59 -02:00
parent d913d6695f
commit 3acc9559a3
4 changed files with 109 additions and 21 deletions

View file

@ -161,10 +161,10 @@ enum PageControl : uint8_t {
// Operation Codes
enum Operations : uint8_t {
OpModeSense10 = 0x5A, // MODE SENSE (10 bytes)
OpReadCapacity = 0x25, // READ CAPACITY
OpRequestSense = 0x03, // REQUEST SENSE
OpTestUnitReady = 0x00, // TEST UNIT READY
OpModeSense10 = 0x5A, // (0x5A) MODE SENSE (10 bytes)
OpReadCapacity = 0x25, // (0x25) READ CAPACITY
OpRequestSense = 0x03, // (0x03) REQUEST SENSE
OpTestUnitReady = 0x00, // (0x00) TEST UNIT READY
};
// ----- Operation data -------------------------------------------------------

View file

@ -17,7 +17,7 @@ inline uint16_t B2L16(uint8_t bytes[2]) {
// Converts a 24-bit unsigned integer from big-endian to little-endian.
inline uint32_t B2L24(uint8_t high, uint8_t low[2]) {
return (high << 24) | B2L16(low);
return (high << 16) | B2L16(low);
}
// Converts a 32-bit unsigned integer from big-endian to little-endian.
@ -31,6 +31,40 @@ inline uint64_t B2L64(uint8_t bytes[8]) {
| ((uint64_t)bytes[4] << 24L) | ((uint64_t)bytes[5] << 16L) | ((uint64_t)bytes[6] << 8L) | (uint64_t)bytes[7];
}
// Converts a 16-bit unsigned integer from little-endian to big-endian.
inline void L2B16(uint8_t bytes[2], uint16_t val) {
bytes[0] = val >> 8;
bytes[1] = val;
}
// Converts a 24-bit unsigned integer from little-endian to big-endian.
inline void L2B24(uint8_t *high, uint8_t low[2], uint32_t val) {
*high = val >> 16;
low[0] = val >> 8;
low[1] = val;
}
// Converts a 32-bit unsigned integer from little-endian to big-endian.
inline void L2B32(uint8_t bytes[4], uint32_t val) {
bytes[0] = val >> 24;
bytes[1] = val >> 16;
bytes[2] = val >> 8;
bytes[3] = val;
}
// Converts a 64-bit unsigned integer from little-endian to big-endian.
inline void L2B64(uint8_t bytes[8], uint64_t val) {
bytes[0] = val >> 56L;
bytes[1] = val >> 48L;
bytes[2] = val >> 40L;
bytes[3] = val >> 32L;
bytes[4] = val >> 24L;
bytes[5] = val >> 16L;
bytes[6] = val >> 8L;
bytes[7] = val;
}
}
}
}

View file

@ -134,10 +134,10 @@ bool BaseDVDDriveATADeviceDriver::ValidateCommand(PacketInformation& packetInfo)
// TODO: is it correct to fail if the length is smaller than the page data?
if (B2L16(packetInfo.cdb.modeSense10.length) < sizeof(XboxDVDAuthentication)) {
packetInfo.result.aborted = true;
packetInfo.result.incorrectLength = true;
packetInfo.result.status = StCheckCondition;
packetInfo.result.senseKey = SKIllegalRequest;
packetInfo.result.additionalSenseCode = ASCInvalidFieldInCDB;
packetInfo.result.incorrectLength = true;
return false;
}
packetInfo.transferSize = sizeof(XboxDVDAuthentication);
@ -147,6 +147,9 @@ bool BaseDVDDriveATADeviceDriver::ValidateCommand(PacketInformation& packetInfo)
case OpRequestSense:
packetInfo.transferSize = packetInfo.cdb.requestSense.length;
return true;
case OpReadCapacity:
packetInfo.transferSize = sizeof(ReadCapacityData);
return true;
default:
return true;
}

View file

@ -14,11 +14,15 @@
#include "vixen/log.h"
#include "vixen/io.h"
#include "vixen/hw/ata/atapi_defs.h"
#include "vixen/hw/ata/atapi_xbox.h"
#include "vixen/hw/ata/atapi_utils.h"
namespace vixen {
namespace hw {
namespace ata {
using namespace atapi;
DummyDVDDriveATADeviceDriver::DummyDVDDriveATADeviceDriver() {
strcpy(m_serialNumber, "1234567890");
strcpy(m_firmwareRevision, "1.00");
@ -41,8 +45,8 @@ bool DummyDVDDriveATADeviceDriver::Write(uint64_t byteAddress, uint8_t *buffer,
return false;
}
bool DummyDVDDriveATADeviceDriver::ValidateATAPIPacket(atapi::PacketInformation& packetInfo) {
log_debug("DummyDVDDriveATADeviceDriver::ValidateATAPIPacket: Operation Code 0x%x -> Command Code 0x%x Group Code 0x%x\n", packetInfo.cdb.opCode.u8, packetInfo.cdb.opCode.fields.commandCode, packetInfo.cdb.opCode.fields.groupCode);
bool DummyDVDDriveATADeviceDriver::ValidateATAPIPacket(PacketInformation& packetInfo) {
log_debug("DummyDVDDriveATADeviceDriver::ValidateATAPIPacket: Operation code 0x%x\n", packetInfo.cdb.opCode.u8, packetInfo.cdb.opCode.fields.commandCode, packetInfo.cdb.opCode.fields.groupCode);
// TODO: device-specific validation
@ -50,24 +54,71 @@ bool DummyDVDDriveATADeviceDriver::ValidateATAPIPacket(atapi::PacketInformation&
return ValidateCommand(packetInfo);
}
bool DummyDVDDriveATADeviceDriver::ProcessATAPIPacketNonData(atapi::PacketInformation& packetInfo) {
log_debug("DummyDVDDriveATADeviceDriver::ProcessATAPIPacketNonData: Operation Code 0x%x -> Command Code 0x%x Group Code 0x%x\n", packetInfo.cdb.opCode.u8, packetInfo.cdb.opCode.fields.commandCode, packetInfo.cdb.opCode.fields.groupCode);
// TODO: implement
return false;
bool DummyDVDDriveATADeviceDriver::ProcessATAPIPacketNonData(PacketInformation& packetInfo) {
switch (packetInfo.cdb.opCode.u8) {
case OpTestUnitReady:
// Say that there is no disc in the drive
packetInfo.result.status = StCheckCondition;
packetInfo.result.senseKey = SKNotReady;
packetInfo.result.additionalSenseCode = ASCMediumNotPresent;
return true;
default:
log_debug("DummyDVDDriveATADeviceDriver::ProcessATAPIPacketNonData: Unimplemented operation code 0x%x\n", packetInfo.cdb.opCode.u8);
return false;
}
}
bool DummyDVDDriveATADeviceDriver::ProcessATAPIPacketDataRead(atapi::PacketInformation& packetInfo, uint8_t *packetDataBuffer, uint16_t byteCountLimit, uint32_t *packetDataSize) {
log_debug("DummyDVDDriveATADeviceDriver::ProcessATAPIPacketDataRead: Operation Code 0x%x -> Command Code 0x%x Group Code 0x%x byte count limit = 0x%x\n", packetInfo.cdb.opCode.u8, packetInfo.cdb.opCode.fields.commandCode, packetInfo.cdb.opCode.fields.groupCode, byteCountLimit);
// TODO: implement
return false;
bool DummyDVDDriveATADeviceDriver::ProcessATAPIPacketDataRead(PacketInformation& packetInfo, uint8_t *packetDataBuffer, uint16_t byteCountLimit, uint32_t *packetDataSize) {
switch (packetInfo.cdb.opCode.u8) {
case OpModeSense10:
switch (packetInfo.cdb.modeSense10.pageCode) {
case kPageCodeAuthentication:
{
// TODO: handle partial reads
if (byteCountLimit < sizeof(XboxDVDAuthentication)) {
packetInfo.result.aborted = true;
packetInfo.result.deviceFault = true;
return false;
}
// Fill in just enough information to pass basic authentication checks on modified kernels
// TODO: Research Xbox DVD authentication
// https://multimedia.cx/eggs/xbox-sphinx-protocol/
XboxDVDAuthentication *dvdAuth = reinterpret_cast<XboxDVDAuthentication *>(packetDataBuffer);
dvdAuth->CDFValid = 1;
dvdAuth->PartitionArea = 1;
dvdAuth->Authentication = 1;
*packetDataSize = sizeof(XboxDVDAuthentication);
return true;
}
default:
log_debug("DummyDVDDriveATADeviceDriver::ProcessATAPIPacketDataRead: Unimplemented page code 0x%x for MODE SENSE(10)\n", packetInfo.cdb.modeSense10.pageCode);
return false;
}
case OpReadCapacity:
{
// Say that there is no disc in the drive
packetInfo.result.status = StCheckCondition;
packetInfo.result.senseKey = SKNotReady;
packetInfo.result.additionalSenseCode = ASCMediumNotPresent;
ReadCapacityData *capData = reinterpret_cast<ReadCapacityData *>(packetDataBuffer);
L2B32(capData->lba, 0);
L2B32(capData->blockLength, 0);
*packetDataSize = sizeof(ReadCapacityData);
return true;
}
default:
log_debug("DummyDVDDriveATADeviceDriver::ProcessATAPIPacketDataRead: Unimplemented operation code 0x%x\n", packetInfo.cdb.opCode.u8);
return false;
}
}
bool DummyDVDDriveATADeviceDriver::ProcessATAPIPacketDataWrite(atapi::PacketInformation& packetInfo, uint8_t *packetDataBuffer, uint16_t byteCountLimit) {
log_debug("DummyDVDDriveATADeviceDriver::ProcessATAPIPacketDataWrite: Operation Code 0x%x -> Command Code 0x%x Group Code 0x%x byte count limit = 0x%x\n", packetInfo.cdb.opCode.u8, packetInfo.cdb.opCode.fields.commandCode, packetInfo.cdb.opCode.fields.groupCode, byteCountLimit);
bool DummyDVDDriveATADeviceDriver::ProcessATAPIPacketDataWrite(PacketInformation& packetInfo, uint8_t *packetDataBuffer, uint16_t byteCountLimit) {
// TODO: implement
log_debug("DummyDVDDriveATADeviceDriver::ProcessATAPIPacketDataWrite: Unimplemented operation code 0x%x\n", packetInfo.cdb.opCode.u8);
return false;
}