diff --git a/src/add-ons/kernel/bus_managers/ata/ATAChannel.cpp b/src/add-ons/kernel/bus_managers/ata/ATAChannel.cpp index 578f61914a..33b7f298fe 100644 --- a/src/add-ons/kernel/bus_managers/ata/ATAChannel.cpp +++ b/src/add-ons/kernel/bus_managers/ata/ATAChannel.cpp @@ -755,7 +755,7 @@ ATAChannel::ExecutePIOTransfer(ATARequest *request) status_t result = B_OK; size_t *bytesLeft = request->BytesLeft(); while (*bytesLeft > 0) { - size_t currentLength = MIN(*bytesLeft, ATA_BLOCK_SIZE); + size_t currentLength = MIN(*bytesLeft, request->Device()->BlockSize()); if (request->IsWrite()) { result = _WritePIOBlock(request, currentLength); if (result != B_OK) { diff --git a/src/add-ons/kernel/bus_managers/ata/ATADevice.cpp b/src/add-ons/kernel/bus_managers/ata/ATADevice.cpp index abf3e9f65b..4317c8ec74 100644 --- a/src/add-ons/kernel/bus_managers/ata/ATADevice.cpp +++ b/src/add-ons/kernel/bus_managers/ata/ATADevice.cpp @@ -17,9 +17,12 @@ ATADevice::ATADevice(ATAChannel *channel, uint8 index) fUseDMA(channel->UseDMA()), fDMAMode(0), fDMAFailures(0), + fTotalSectors(0), + fBlockSize(512), + fPhysicalBlockSize(512), + fBlockOffset(0), fIndex(index), - fUse48Bits(false), - fTotalSectors(0) + fUse48Bits(false) { memset(&fInfoBlock, 0, sizeof(fInfoBlock)); memset(&fTaskFile, 0, sizeof(fTaskFile)); @@ -170,7 +173,7 @@ ATADevice::ReadCapacity(ATARequest *request) } scsi_res_read_capacity data; - data.block_size = B_HOST_TO_BENDIAN_INT32(ATA_BLOCK_SIZE); + data.block_size = B_HOST_TO_BENDIAN_INT32(fBlockSize); uint32 lastBlock = fTotalSectors - 1; data.lba = B_HOST_TO_BENDIAN_INT32(lastBlock); @@ -305,12 +308,12 @@ status_t ATADevice::Select() { status_t err = fChannel->SelectDevice(fIndex); -#if 1 - // for debugging only +#if 1 + // for debugging only if (fChannel->SelectedDevice() != fIndex) { TRACE_ERROR("device %d not selected!\n", fIndex); - return B_ERROR; - } + return B_ERROR; + } #endif return err; } @@ -442,6 +445,23 @@ ATADevice::Configure() } fTotalSectors = fInfoBlock.lba_sector_count; + + if (fInfoBlock.word_106_bit_14_one && !fInfoBlock.word_106_bit_15_zero) { + // contains a valid block size configuration + if (fInfoBlock.logical_sector_not_512_bytes) + fBlockSize = fInfoBlock.logical_sector_size * 2; + + if (fInfoBlock.multiple_logical_per_physical_sectors) { + fPhysicalBlockSize + = fBlockSize << fInfoBlock.logical_sectors_per_physical_sector; + } else + fPhysicalBlockSize = fBlockSize; + } + if (fInfoBlock.word_209_bit_14_one && !fInfoBlock.word_209_bit_15_zero) { + // contains a valid logical block offset configuration + fBlockOffset = fInfoBlock.logical_sector_offset; + } + fTaskFile.lba.mode = ATA_MODE_LBA; fTaskFile.lba.device = fIndex; @@ -540,7 +560,7 @@ ATADevice::ExecuteReadWrite(ATARequest *request, uint64 address, if (!request->UseDMA()) request->PrepareSGInfo(); - request->SetBytesLeft(sectorCount * ATA_BLOCK_SIZE); + request->SetBytesLeft(sectorCount * fBlockSize); if (_FillTaskFile(request, address) != B_OK) { TRACE_ERROR("failed to setup transfer request\n"); if (request->UseDMA()) @@ -615,7 +635,7 @@ ATADevice::_FillTaskFile(ATARequest *request, uint64 address) { ATA_COMMAND_READ_DMA, ATA_COMMAND_WRITE_DMA } }; - uint32 sectorCount = *request->BytesLeft() / ATA_BLOCK_SIZE; + uint32 sectorCount = *request->BytesLeft() / fBlockSize; TRACE("about to transfer %lu sectors\n", sectorCount); if (fUse48Bits diff --git a/src/add-ons/kernel/bus_managers/ata/ATAPrivate.h b/src/add-ons/kernel/bus_managers/ata/ATAPrivate.h index c59ae4f685..2ff101f124 100644 --- a/src/add-ons/kernel/bus_managers/ata/ATAPrivate.h +++ b/src/add-ons/kernel/bus_managers/ata/ATAPrivate.h @@ -1,7 +1,7 @@ /* * Copyright 2009, Michael Lotz, mmlr@mlotz.ch. * Copyright 2008, Marcus Overhagen. - * Copyright 2004-2008, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2004-2010, Axel Dörfler, axeld@pinc-software.de. * Copyright 2002-2003, Thomas Kurschel. * * Distributed under the terms of the MIT License. @@ -9,6 +9,7 @@ #ifndef ATA_PRIVATE_H #define ATA_PRIVATE_H + #include #include #include @@ -25,7 +26,7 @@ #include "ATAInfoblock.h" #include "ATATracing.h" -#define ATA_BLOCK_SIZE 512 /* TODO: retrieve */ + #define ATA_MAX_DMA_FAILURES 3 #define ATA_STANDARD_TIMEOUT 10 * 1000 * 1000 #define ATA_RELEASE_TIMEOUT 10 * 1000 * 1000 @@ -183,15 +184,17 @@ virtual status_t ExecuteIO(ATARequest *request); uint32 *maxBlocks); // ATA stuff -virtual bool IsATAPI() { return false; }; +virtual bool IsATAPI() const { return false; } - bool UseDMA() { return fUseDMA; }; - bool Use48Bits() { return fUse48Bits; }; + bool UseDMA() const { return fUseDMA; } + bool Use48Bits() const { return fUse48Bits; } + size_t BlockSize() const { return fBlockSize; } status_t Select(); - ata_task_file * TaskFile() { return &fTaskFile; }; - ata_reg_mask RegisterMask() { return fRegisterMask; }; + ata_task_file * TaskFile() { return &fTaskFile; } + ata_reg_mask RegisterMask() const + { return fRegisterMask; } status_t SetFeature(int feature); status_t DisableCommandQueueing(); @@ -219,9 +222,12 @@ private: status_t _FillTaskFile(ATARequest *request, uint64 address); + uint64 fTotalSectors; + size_t fBlockSize; + size_t fPhysicalBlockSize; + size_t fBlockOffset; uint8 fIndex; bool fUse48Bits; - uint64 fTotalSectors; char fDebugContext[16]; };