mmc_disk: add write support

Change-Id: I77cf1612569c43e79917ac5a1493b7ab4a04cb47
Reviewed-on: https://review.haiku-os.org/c/haiku/+/3504
Reviewed-by: Alex von Gluck IV <kallisti5@unixzen.com>
This commit is contained in:
Adrien Destugues 2020-12-13 12:25:03 +01:00 committed by waddlesplash
parent 7a160a8629
commit 9a37366b51
6 changed files with 45 additions and 17 deletions

View File

@ -42,10 +42,13 @@ enum SD_COMMANDS {
SD_SEND_CSD = 9,
SD_STOP_TRANSMISSION = 12,
// Block oriented read commands, class 2
// Block oriented read and write commands, class 2
SD_READ_SINGLE_BLOCK = 17,
SD_READ_MULTIPLE_BLOCKS = 18,
SD_WRITE_SINGLE_BLOCK = 24,
SD_WRITE_MULTIPLE_BLOCKS = 25,
// Application specific commands, class 8
SD_APP_CMD = 55,
@ -65,19 +68,32 @@ typedef struct mmc_bus_interface {
driver_module_info info;
status_t (*set_clock)(void* controller, uint32_t kilohertz);
// Configure the bus clock. The bus is initialized with a slow clock
// that allows device enumeration in all cases, but after enumeration
// the mmc_bus knows how fast each card can go, and configures the bus
// accordingly.
status_t (*execute_command)(void* controller, uint8_t command,
uint32_t argument, uint32_t* result);
status_t (*do_io)(void* controller, IOOperation* operation);
// Execute a command with no I/O phase
status_t (*do_io)(void* controller, uint8_t command,
IOOperation* operation);
// Execute a command that involves a data transfer.
} mmc_bus_interface;
// Interface between mmc device driver (mmc_disk, sdio drivers, ...) and mmc_bus
// This interface is rather generic as it allows implementation of drivers for
// different type of cards, which will use different commands. The bus
// provides a generic interface for all of them, and is not specific to any
// type of card.
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);
// Execute a command with no I/O phase
status_t (*do_io)(device_node* controller, uint16_t rca,
IOOperation* operation);
uint8_t command, IOOperation* operation);
// Execute a command that involves a data transfer.
} mmc_device_interface;

View File

@ -86,12 +86,12 @@ MMCBus::ExecuteCommand(uint8_t command, uint32_t argument, uint32_t* response)
status_t
MMCBus::DoIO(uint16_t rca, IOOperation* operation)
MMCBus::DoIO(uint16_t rca, uint8_t command, IOOperation* operation)
{
status_t status = _ActivateDevice(rca);
if (status != B_OK)
return status;
return fController->do_io(fCookie, operation);
return fController->do_io(fCookie, command, operation);
}

View File

@ -43,7 +43,8 @@ public:
status_t ExecuteCommand(uint8_t command,
uint32_t argument, uint32_t* response);
status_t DoIO(uint16_t rca, IOOperation* operation);
status_t DoIO(uint16_t rca, uint8_t command,
IOOperation* operation);
void AcquireBus() { acquire_sem(fLockSemaphore); }
void ReleaseBus() { release_sem(fLockSemaphore); }

View File

@ -103,7 +103,8 @@ mmc_bus_execute_command(device_node* node, uint8_t command, uint32_t argument,
static status_t
mmc_bus_do_io(device_node* node, uint16_t rca, IOOperation* operation)
mmc_bus_do_io(device_node* node, uint16_t rca, uint8_t command,
IOOperation* operation)
{
driver_module_info* mmc;
void* cookie;
@ -118,7 +119,7 @@ mmc_bus_do_io(device_node* node, uint16_t rca, IOOperation* operation)
bus->AcquireBus();
status_t result = B_OK;
result = bus->DoIO(rca, operation);
result = bus->DoIO(rca, command, operation);
bus->ReleaseBus();
return result;

View File

@ -52,7 +52,7 @@ class SdhciBus {
status_t InitCheck();
void Reset();
void SetClock(int kilohertz);
status_t DoIO(IOOperation* operation);
status_t DoIO(uint8_t command, IOOperation* operation);
private:
bool PowerOn();
@ -196,6 +196,8 @@ SdhciBus::ExecuteCommand(uint8_t command, uint32_t argument, uint32_t* response)
break;
case SD_READ_SINGLE_BLOCK:
case SD_READ_MULTIPLE_BLOCKS:
case SD_WRITE_SINGLE_BLOCK:
case SD_WRITE_MULTIPLE_BLOCKS:
replyType = Command::kR1Type | Command::kDataPresent;
break;
case SD_APP_CMD:
@ -338,11 +340,9 @@ SdhciBus::SetClock(int kilohertz)
status_t
SdhciBus::DoIO(IOOperation* operation)
SdhciBus::DoIO(uint8_t command, IOOperation* operation)
{
bool isWrite = operation->IsWrite();
if (isWrite)
return B_NOT_SUPPORTED;
static const uint32 kBlockSize = 512;
off_t offset = operation->Offset();
@ -384,11 +384,16 @@ SdhciBus::DoIO(IOOperation* operation)
fRegisters->block_count = toCopy / kBlockSize;
fRegisters->transfer_mode = TransferMode::kSingle | TransferMode::kRead
uint16 direction;
if (isWrite)
direction = TransferMode::kWrite;
else
direction = TransferMode::kRead;
fRegisters->transfer_mode = TransferMode::kMulti | direction
| TransferMode::kAutoCmd12Enable | TransferMode::kDmaEnable;
uint32_t response;
result = ExecuteCommand(SD_READ_MULTIPLE_BLOCKS, offset, &response);
result = ExecuteCommand(command, offset, &response);
if (result != B_OK)
break;
@ -780,12 +785,12 @@ execute_command(void* controller, uint8_t command, uint32_t argument,
static status_t
do_io(void* controller, IOOperation* operation)
do_io(void* controller, uint8_t command, IOOperation* operation)
{
CALLED();
SdhciBus* bus = (SdhciBus*)controller;
return bus->DoIO(operation);
return bus->DoIO(command, operation);
}

View File

@ -110,7 +110,12 @@ 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);
uint8_t command;
if (operation->IsWrite())
command = SD_WRITE_MULTIPLE_BLOCKS;
else
command = SD_READ_MULTIPLE_BLOCKS;
error = info->mmc->do_io(info->parent, info->rca, command, operation);
if (error != B_OK) {
info->scheduler->OperationCompleted(operation, error, 0);