diff --git a/headers/private/drivers/mmc.h b/headers/private/drivers/mmc.h index aa34a01f4d..815d97488c 100644 --- a/headers/private/drivers/mmc.h +++ b/headers/private/drivers/mmc.h @@ -15,6 +15,9 @@ #define MMC_BUS_MODULE_NAME "bus_managers/mmc/driver_v1" +struct IOOperation; + + enum { CARD_TYPE_MMC, CARD_TYPE_SD, @@ -64,8 +67,7 @@ typedef struct mmc_bus_interface { status_t (*set_clock)(void* controller, uint32_t kilohertz); status_t (*execute_command)(void* controller, uint8_t command, uint32_t argument, uint32_t* result); - status_t (*read_naive)(void* controller, off_t pos, - void* buffer, size_t* _length); + status_t (*do_io)(void* controller, IOOperation* operation); } mmc_bus_interface; @@ -74,8 +76,8 @@ typedef struct mmc_device_interface { driver_module_info info; status_t (*execute_command)(device_node* node, uint8_t command, uint32_t argument, uint32_t* result); - status_t (*read_naive)(device_node* controller, uint16_t rca, off_t pos, - void* buffer, size_t* _length); + status_t (*do_io)(device_node* controller, uint16_t rca, + IOOperation* operation); } mmc_device_interface; diff --git a/src/add-ons/kernel/bus_managers/mmc/mmc_bus.cpp b/src/add-ons/kernel/bus_managers/mmc/mmc_bus.cpp index de625f0e1e..096e8f5b4a 100644 --- a/src/add-ons/kernel/bus_managers/mmc/mmc_bus.cpp +++ b/src/add-ons/kernel/bus_managers/mmc/mmc_bus.cpp @@ -86,12 +86,12 @@ MMCBus::ExecuteCommand(uint8_t command, uint32_t argument, uint32_t* response) status_t -MMCBus::Read(uint16_t rca, off_t position, void* buffer, size_t* length) +MMCBus::DoIO(uint16_t rca, IOOperation* operation) { status_t status = _ActivateDevice(rca); if (status != B_OK) return status; - return fController->read_naive(fCookie, position, buffer, length); + return fController->do_io(fCookie, operation); } diff --git a/src/add-ons/kernel/bus_managers/mmc/mmc_bus.h b/src/add-ons/kernel/bus_managers/mmc/mmc_bus.h index 9692ef9489..bf39bdc93c 100644 --- a/src/add-ons/kernel/bus_managers/mmc/mmc_bus.h +++ b/src/add-ons/kernel/bus_managers/mmc/mmc_bus.h @@ -43,8 +43,7 @@ public: status_t ExecuteCommand(uint8_t command, uint32_t argument, uint32_t* response); - status_t Read(uint16_t rca, off_t position, void* buffer, - size_t* length); + status_t DoIO(uint16_t rca, IOOperation* operation); void AcquireBus() { acquire_sem(fLockSemaphore); } void ReleaseBus() { release_sem(fLockSemaphore); } diff --git a/src/add-ons/kernel/bus_managers/mmc/mmc_module.cpp b/src/add-ons/kernel/bus_managers/mmc/mmc_module.cpp index c0ce6e5c36..6c713e83c3 100644 --- a/src/add-ons/kernel/bus_managers/mmc/mmc_module.cpp +++ b/src/add-ons/kernel/bus_managers/mmc/mmc_module.cpp @@ -1,9 +1,10 @@ /* - * Copyright 2018 Haiku, Inc. All rights reserved. + * Copyright 2018-2021 Haiku, Inc. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: * B Krishnan Iyer, krishnaniyer97@gmail.com + * Adrien Destugues, pulkomandy@pulkomandy.tk */ #include "mmc_bus.h" @@ -102,21 +103,23 @@ mmc_bus_execute_command(device_node* node, uint8_t command, uint32_t argument, static status_t -mmc_bus_read_naive(device_node* node, uint16_t rca, off_t pos, void* buffer, - size_t* _length) +mmc_bus_do_io(device_node* node, uint16_t rca, IOOperation* operation) { - // FIXME store the parent cookie in the bus cookie or something instead of - // getting/putting the parent each time. driver_module_info* mmc; void* cookie; + // FIXME store the parent cookie in the bus cookie or something instead of + // getting/putting the parent each time. device_node* parent = gDeviceManager->get_parent_node(node); gDeviceManager->get_driver(parent, &mmc, &cookie); gDeviceManager->put_node(parent); MMCBus* bus = (MMCBus*)cookie; bus->AcquireBus(); - status_t result = bus->Read(rca, pos, buffer, _length); + status_t result = B_OK; + + result = bus->DoIO(rca, operation); + bus->ReleaseBus(); return result; } @@ -172,7 +175,7 @@ mmc_device_interface mmc_bus_controller_module = { NULL }, mmc_bus_execute_command, - mmc_bus_read_naive + mmc_bus_do_io }; diff --git a/src/add-ons/kernel/busses/mmc/Jamfile b/src/add-ons/kernel/busses/mmc/Jamfile index 5b6f27ba7c..9b8fc1c754 100644 --- a/src/add-ons/kernel/busses/mmc/Jamfile +++ b/src/add-ons/kernel/busses/mmc/Jamfile @@ -2,7 +2,9 @@ SubDir HAIKU_TOP src add-ons kernel busses mmc ; SubDirC++Flags -fno-rtti ; +UsePrivateKernelHeaders ; UsePrivateHeaders drivers ; +SubDirHdrs $(HAIKU_TOP) src system kernel device_manager ; KernelAddon sdhci_pci : sdhci_pci.cpp diff --git a/src/add-ons/kernel/busses/mmc/sdhci_pci.cpp b/src/add-ons/kernel/busses/mmc/sdhci_pci.cpp index 3700c8c255..82bdfe616f 100644 --- a/src/add-ons/kernel/busses/mmc/sdhci_pci.cpp +++ b/src/add-ons/kernel/busses/mmc/sdhci_pci.cpp @@ -4,7 +4,9 @@ * * Authors: * B Krishnan Iyer, krishnaniyer97@gmail.com + * Adrien Destugues, pulkomandy@pulkomandy.tk */ +#include #include #include #include @@ -14,6 +16,7 @@ #include +#include "IOSchedulerSimple.h" #include "mmc.h" #include "sdhci_pci.h" @@ -49,7 +52,7 @@ class SdhciBus { status_t InitCheck(); void Reset(); void SetClock(int kilohertz); - status_t ReadNaive(off_t pos, void* buffer, size_t* _length); + status_t DoIO(IOOperation* operation); private: bool PowerOn(); @@ -114,8 +117,8 @@ SdhciBus::SdhciBus(struct registers* registers, uint8_t irq) return; } - EnableInterrupts(SDHCI_INT_CMD_CMP - | SDHCI_INT_BUF_READ_READY | SDHCI_INT_CARD_INS | SDHCI_INT_CARD_REM); + EnableInterrupts(SDHCI_INT_CMD_CMP | SDHCI_INT_CARD_INS + | SDHCI_INT_CARD_REM | SDHCI_INT_TRANS_CMP); // We want to see the error bits in the status register, but not have an // interrupt trigger on them (we get a "command complete" interrupt on @@ -224,9 +227,10 @@ SdhciBus::ExecuteCommand(uint8_t command, uint32_t argument, uint32_t* response) fRegisters->argument = argument; fRegisters->command.SendCommand(command, replyType); - // Wait for command response to be available (either "command complete" or - // "buffer read ready" interrupt will happen, depending on the command) + // Wait for command response to be available ("command complete" interrupt) + TRACE("Wait for command complete..."); acquire_sem(fSemaphore); + TRACE("command complete OK\n"); if (fCommandResult & SDHCI_INT_ERROR) { fRegisters->interrupt_status |= fCommandResult; @@ -267,6 +271,12 @@ SdhciBus::ExecuteCommand(uint8_t command, uint32_t argument, uint32_t* response) break; } + if (replyType == Command::kR1bType) { + // R1b commands may use the data line so we must wait for the + // "transfer complete" interrupt here. + acquire_sem(fSemaphore); + } + ERROR("Command execution %d complete\n", command); return B_OK; } @@ -328,57 +338,75 @@ SdhciBus::SetClock(int kilohertz) status_t -SdhciBus::ReadNaive(off_t pos, void* buffer, size_t* _length) +SdhciBus::DoIO(IOOperation* operation) { - // TODO read multiple blocks at once (don't ignore _length) - fRegisters->block_size = 512; - fRegisters->block_count = 1; - fRegisters->transfer_mode = TransferMode::kSingle | TransferMode::kRead - | TransferMode::kAutoCmdDisabled | TransferMode::kNoDmaOrNoData; + bool isWrite = operation->IsWrite(); + if (isWrite) + return B_NOT_SUPPORTED; - uint32_t response; - status_t result; - result = ExecuteCommand(SD_READ_SINGLE_BLOCK, pos, &response); + static const uint32 kBlockSize = 512; + off_t offset = operation->Offset(); + generic_size_t length = operation->Length(); + + TRACE("%s %ld bytes at %ld\n", isWrite ? "Write" : "Read", length, offset); + + // Check that the IO scheduler did its job in following our DMA restrictions + // We can start a read only at a sector boundary + ASSERT(offset % kBlockSize == 0); + // We can only read complete sectors + ASSERT(length % kBlockSize == 0); + + const generic_io_vec* vecs = operation->Vecs(); + generic_size_t vecOffset = 0; + + // Must always be 512 (on SD cards it can be changed, but not on SDHC) + // FIXME can this be moved to the init function instead? + fRegisters->block_size = kBlockSize; + status_t result = B_OK; + + while (length > 0) { + size_t toCopy = std::min((generic_size_t)length, + vecs->length - vecOffset); + TRACE("Reading loop %ld bytes from position %ld\n", toCopy, offset); + + // If the current vec is empty, we can move to the next + if (toCopy == 0) { + vecs++; + vecOffset = 0; + continue; + } + + // With SDMA we can only transfer multiples of 1 sector + ASSERT(toCopy % kBlockSize == 0); + + fRegisters->system_address = vecs->base + vecOffset; + // fRegisters->adma_system_address = fDmaMemory; + + fRegisters->block_count = toCopy / kBlockSize; + + fRegisters->transfer_mode = TransferMode::kSingle | TransferMode::kRead + | TransferMode::kAutoCmd12Enable | TransferMode::kDmaEnable; + + uint32_t response; + result = ExecuteCommand(SD_READ_MULTIPLE_BLOCKS, offset, &response); + if (result != B_OK) + break; + + // Wait for DMA transfer to complete + // In theory we could go on and send other commands as long as they + // don't need the DAT lines, but it's overcomplicating things. + TRACE("Wait for transfer complete..."); + acquire_sem(fSemaphore); + TRACE("transfer complete OK.\n"); + + length -= toCopy; + vecOffset += toCopy; + offset += toCopy; + } if (result != B_OK) return result; - TRACE("Command response: %02x\n", response); - - if (fCommandResult & SDHCI_INT_BUF_READ_READY == 0) { - TRACE("No data!\n"); - return B_ERROR; - } - - // We don't know how to read more than 512 bytes (CMD18 would be needed) - if (*_length > 512) - *_length = 512; - - // read block data from Buffer Data Port register - // TODO use DMA instead - size_t to_read = *_length / sizeof(uint32_t); - size_t to_drop = 512 / sizeof(uint32_t) - to_read; - uint32_t* dest = (uint32_t*)buffer; - while(to_read > 0) { - *dest = fRegisters->buffer_data_port; - TRACE("read : 0x%x", *dest); - dest++; - to_read--; - } - - // We cannot read less than one sector, so we have to drop the extra data. - // This will be fixed when we use DMA and the IO scheduler (since it makes - // sure to only ask for complete sectors). - // Currently the IO scheduler does not support bounce buffers for non-DMA - // transfers. - while(to_drop > 0) { - (void*)fRegisters->buffer_data_port; - to_drop--; - } - - // wait for command complete interrupt - acquire_sem(fSemaphore); - return B_OK; } @@ -526,8 +554,6 @@ SdhciBus::RecoverError() int32 SdhciBus::HandleInterrupt() { - CALLED(); - #if 0 // We could use the slot register to quickly see for which slot the // interrupt is. But since we have an interrupt handler call for each slot @@ -578,12 +604,10 @@ SdhciBus::HandleInterrupt() TRACE("Command complete interrupt handled\n"); } - // handling data transfer interrupt - if (intmask & SDHCI_INT_BUF_READ_READY) { - TRACE("buffer read ready interrupt raised"); - fRegisters->interrupt_status |= (intmask & SDHCI_INT_BUF_READ_READY); - + if (intmask & SDHCI_INT_TRANS_CMP) { + fRegisters->interrupt_status |= SDHCI_INT_TRANS_CMP; release_sem_etc(fSemaphore, 1, B_DO_NOT_RESCHEDULE); + TRACE("Transfer complete interrupt handled\n"); } // handling bus power interrupt @@ -755,14 +779,13 @@ execute_command(void* controller, uint8_t command, uint32_t argument, } -//Very naive read protocol : non DMA, 32 bits at a time (size of Buffer Data Port) static status_t -read_naive(void* controller, off_t pos, void* buffer, size_t* _length) +do_io(void* controller, IOOperation* operation) { CALLED(); SdhciBus* bus = (SdhciBus*)controller; - return bus->ReadNaive(pos, buffer, _length); + return bus->DoIO(operation); } @@ -793,7 +816,7 @@ static mmc_bus_interface gSDHCIPCIDeviceModule = { set_clock, execute_command, - read_naive + do_io }; diff --git a/src/add-ons/kernel/busses/mmc/sdhci_pci.h b/src/add-ons/kernel/busses/mmc/sdhci_pci.h index 00dbc7a0fb..f1fa632159 100644 --- a/src/add-ons/kernel/busses/mmc/sdhci_pci.h +++ b/src/add-ons/kernel/busses/mmc/sdhci_pci.h @@ -38,8 +38,8 @@ class TransferMode { static const uint8_t kAutoCmdDisabled = 0 << 2; static const uint8_t kAutoCmd12Enable = 1 << 2; static const uint8_t kAutoCmd23Enable = 2 << 2; - static const uint8_t kAutoCmdAutoSelect = - kAutoCmd23Enable | kAutoCmd12Enable; + static const uint8_t kAutoCmdAutoSelect + = kAutoCmd23Enable | kAutoCmd12Enable; // TODO block count enable @@ -65,7 +65,7 @@ class Command { static const uint8_t kSubCommand = 0x4; static const uint8_t kReplySizeMask = 0x3; static const uint8_t k32BitResponse = 0x2; - static const uint8_t k128BitResponse = 0x1; + static const uint8_t k128BitResponse = 0x1; static const uint8_t k32BitResponseCheckBusy = 0x3; // For simplicity pre-define the standard response types from the SD diff --git a/src/add-ons/kernel/drivers/disk/mmc/mmc_disk.cpp b/src/add-ons/kernel/drivers/disk/mmc/mmc_disk.cpp index 486a84bd32..6a7b54836d 100644 --- a/src/add-ons/kernel/drivers/disk/mmc/mmc_disk.cpp +++ b/src/add-ons/kernel/drivers/disk/mmc/mmc_disk.cpp @@ -10,10 +10,10 @@ #include -#include +#include #include #include -#include +#include #include "mmc_disk.h" #include "mmc_icon.h" @@ -99,8 +99,57 @@ mmc_disk_register_device(device_node* node) { NULL } }; - return sDeviceManager->register_node(node - , MMC_DISK_DRIVER_MODULE_NAME, attrs, NULL, NULL); + return sDeviceManager->register_node(node, MMC_DISK_DRIVER_MODULE_NAME, + attrs, NULL, NULL); +} + + +static status_t +mmc_disk_execute_iorequest(void* data, IOOperation* operation) +{ + mmc_disk_driver_info* info = (mmc_disk_driver_info*)data; + status_t error; + + error = info->mmc->do_io(info->parent, info->rca, operation); + + if (error != B_OK) { + info->scheduler->OperationCompleted(operation, error, 0); + return error; + } + + info->scheduler->OperationCompleted(operation, B_OK, operation->Length()); + return B_OK; +} + + +static status_t +mmc_block_get_geometry(mmc_disk_driver_info* info, device_geometry* geometry) +{ + struct mmc_disk_csd csd; + TRACE("Get geometry\n"); + status_t error = info->mmc->execute_command(info->parent, SD_SEND_CSD, + info->rca << 16, (uint32_t*)&csd); + if (error != B_OK) { + TRACE("Could not get CSD! %s\n", strerror(error)); + return error; + } + + TRACE("CSD: %" PRIx64 " %" PRIx64 "\n", csd.bits[0], csd.bits[1]); + + if (csd.structure_version() < 3) { + geometry->bytes_per_sector = 1 << csd.read_bl_len(); + geometry->sectors_per_track = csd.c_size() + 1; + geometry->cylinder_count = 1 << (csd.c_size_mult() + 2); + geometry->head_count = 1; + geometry->device_type = B_DISK; + geometry->removable = true; // TODO detect eMMC which isn't + geometry->read_only = false; // TODO check write protect switch? + geometry->write_once = false; + return B_OK; + } + + TRACE("unknown CSD version %d\n", csd.structure_version()); + return B_NOT_SUPPORTED; } @@ -131,8 +180,48 @@ mmc_disk_init_driver(device_node* node, void** cookie) return B_BAD_DATA; } - TRACE("MMC card device initialized for RCA %x\n", info->rca); + static const uint32 kBlockSize = 512; // FIXME get it from the CSD + status_t error; + static const uint32 kDMAResourceBufferCount = 16; + static const uint32 kDMAResourceBounceBufferCount = 16; + + // TODO relax this when we have ADMA2 + // TODO the restrictions depend on the SDHCI bus and should be read + // from there, not hardcoded in mmc_disk + const dma_restrictions restrictions = { + 0, UINT32_MAX, /* Only 32bit address space in SDMA mode */ + 512, /* Align requests on sectors start and end */ + B_PAGE_SIZE, /* Do not cross pages (SDMA can't do it) */ + 512, 1, 512}; + + error = info->dmaResource.Init(restrictions, kBlockSize, + kDMAResourceBufferCount, kDMAResourceBounceBufferCount); + if (error != B_OK) { + TRACE("Failed to init DMA resource"); + free(info); + return error; + } + + info->scheduler = new(std::nothrow) IOSchedulerSimple(&info->dmaResource); + if (info->scheduler == NULL) { + TRACE("Failed to allocate scheduler"); + free(info); + return B_NO_MEMORY; + } + + error = info->scheduler->Init("mmc storage"); + if (error != B_OK) { + TRACE("Failed to init scheduler"); + delete info->scheduler; + free(info); + return error; + } + info->scheduler->SetCallback(&mmc_disk_execute_iorequest, info); + + memset(&info->geometry, 0, sizeof(info->geometry)); + + TRACE("MMC card device initialized for RCA %x\n", info->rca); *cookie = info; return B_OK; } @@ -143,6 +232,7 @@ mmc_disk_uninit_driver(void* _cookie) { CALLED(); mmc_disk_driver_info* info = (mmc_disk_driver_info*)_cookie; + delete info->scheduler; sDeviceManager->put_node(info->parent); free(info); } @@ -216,7 +306,7 @@ mmc_block_open(void* _info, const char* path, int openMode, void** _cookie) static status_t mmc_block_close(void* cookie) { - mmc_disk_handle* handle = (mmc_disk_handle*)cookie; + //mmc_disk_handle* handle = (mmc_disk_handle*)cookie; CALLED(); return B_OK; @@ -234,24 +324,82 @@ mmc_block_free(void* cookie) } -static status_t +static status_t mmc_block_read(void* cookie, off_t pos, void* buffer, size_t* _length) { CALLED(); mmc_disk_handle* handle = (mmc_disk_handle*)cookie; - TRACE("Ready to execute %p\n", handle->info->mmc->read_naive); - return handle->info->mmc->read_naive(handle->info->parent, handle->info->rca, pos, buffer, _length); + + size_t length = *_length; + + if (handle->info->geometry.bytes_per_sector == 0) { + status_t error = mmc_block_get_geometry(handle->info, + &handle->info->geometry); + if (error != B_OK) { + TRACE("Failed to get disk capacity"); + return error; + } + } + + // Do not allow reading past device end + if (pos >= handle->info->DeviceSize()) + return B_BAD_VALUE; + if (pos + (off_t)length > handle->info->DeviceSize()) + length = handle->info->DeviceSize() - pos; + + IORequest request; + status_t status = request.Init(pos, (addr_t)buffer, length, false, 0); + if (status != B_OK) + return status; + + status = handle->info->scheduler->ScheduleRequest(&request); + if (status != B_OK) + return status; + + status = request.Wait(0, 0); + if (status == B_OK) + *_length = length; + return status; } static status_t mmc_block_write(void* cookie, off_t position, const void* buffer, - size_t* length) + size_t* _length) { CALLED(); mmc_disk_handle* handle = (mmc_disk_handle*)cookie; - return B_NOT_SUPPORTED; + size_t length = *_length; + + if (handle->info->geometry.bytes_per_sector == 0) { + status_t error = mmc_block_get_geometry(handle->info, + &handle->info->geometry); + if (error != B_OK) { + TRACE("Failed to get disk capacity"); + return error; + } + } + + if (position >= handle->info->DeviceSize()) + return B_BAD_VALUE; + if (position + (off_t)length > handle->info->DeviceSize()) + length = handle->info->DeviceSize() - position; + + IORequest request; + status_t status = request.Init(position, (addr_t)buffer, length, true, 0); + if (status != B_OK) + return status; + + status = handle->info->scheduler->ScheduleRequest(&request); + if (status != B_OK) + return status; + + status = request.Wait(0, 0); + if (status == B_OK) + *_length = length; + + return status; } @@ -261,34 +409,7 @@ mmc_block_io(void* cookie, io_request* request) CALLED(); mmc_disk_handle* handle = (mmc_disk_handle*)cookie; - return B_NOT_SUPPORTED; -} - - -static status_t -mmc_block_get_geometry(mmc_disk_handle* handle, device_geometry* geometry) -{ - struct mmc_disk_csd csd; - TRACE("Ready to execute %p\n", handle->info->mmc->execute_command); - handle->info->mmc->execute_command(handle->info->parent, SD_SEND_CSD, - handle->info->rca << 16, (uint32_t*)&csd); - - TRACE("CSD: %lx %lx\n", csd.bits[0], csd.bits[1]); - - if (csd.structure_version() == 0) { - geometry->bytes_per_sector = 1 << csd.read_bl_len(); - geometry->sectors_per_track = csd.c_size() + 1; - geometry->cylinder_count = 1 << (csd.c_size_mult() + 2); - geometry->head_count = 1; - geometry->device_type = B_DISK; - geometry->removable = true; // TODO detect eMMC which isn't - geometry->read_only = true; // TODO add write support - geometry->write_once = false; - return B_OK; - } - - TRACE("unknown CSD version %d\n", csd.structure_version()); - return B_NOT_SUPPORTED; + return handle->info->scheduler->ScheduleRequest(request); } @@ -316,9 +437,20 @@ mmc_block_ioctl(void* cookie, uint32 op, void* buffer, size_t length) case B_GET_DEVICE_SIZE: { - //size_t size = info->capacity * info->block_size; - //return user_memcpy(buffer, &size, sizeof(size_t)); - return B_NOT_SUPPORTED; + // Legacy ioctl, use B_GET_GEOMETRY + if (info->geometry.bytes_per_sector == 0) { + status_t error = mmc_block_get_geometry(info, &info->geometry); + if (error != B_OK) { + TRACE("Failed to get disk capacity"); + return error; + } + } + + uint64_t size = info->DeviceSize(); + if (size > SIZE_MAX) + return B_NOT_SUPPORTED; + size_t size32 = size; + return user_memcpy(buffer, &size32, sizeof(size_t)); } case B_GET_GEOMETRY: @@ -326,12 +458,16 @@ mmc_block_ioctl(void* cookie, uint32 op, void* buffer, size_t length) if (buffer == NULL || length < sizeof(device_geometry)) return B_BAD_VALUE; - device_geometry geometry; - status_t status = mmc_block_get_geometry(handle, &geometry); - if (status != B_OK) - return status; + if (info->geometry.bytes_per_sector == 0) { + status_t error = mmc_block_get_geometry(info, &info->geometry); + if (error != B_OK) { + TRACE("Failed to get disk capacity"); + return error; + } + } - return user_memcpy(buffer, &geometry, sizeof(device_geometry)); + return user_memcpy(buffer, &info->geometry, + sizeof(device_geometry)); } case B_GET_ICON_NAME: diff --git a/src/add-ons/kernel/drivers/disk/mmc/mmc_disk.h b/src/add-ons/kernel/drivers/disk/mmc/mmc_disk.h index 1775b997ad..fc27a65db8 100644 --- a/src/add-ons/kernel/drivers/disk/mmc/mmc_disk.h +++ b/src/add-ons/kernel/drivers/disk/mmc/mmc_disk.h @@ -17,17 +17,30 @@ #include +#include "IOSchedulerSimple.h" + + +// This is the device info structure, allocated once per device typedef struct { device_node* node; device_node* parent; mmc_device_interface* mmc; uint16_t rca; - size_t block_size; - uint64_t capacity; + device_geometry geometry; + + DMAResource dmaResource; + IOScheduler* scheduler; + + off_t DeviceSize() const { + return (off_t)geometry.bytes_per_sector * geometry.sectors_per_track + * geometry.cylinder_count * geometry.head_count; + } } mmc_disk_driver_info; +// This is allocated once per open() call on the device (there can be multiple +// open file descriptors for the same device) typedef struct { mmc_disk_driver_info* info; } mmc_disk_handle;