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:
parent
7a160a8629
commit
9a37366b51
@ -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;
|
||||
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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); }
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user