Commit 8d0bd7b6 authored by Ben Avison's avatar Ben Avison
Browse files

Support the Raspberry Pi model B+

Detail:
  For removable slots without a card detect pin, use an alternate state
  machine based upon timeouts to detect card removal or card changes. Note
  that this requires cooperation from FileCore (the same code paths as with
  selected floppy drives that had faulty disc changed pins) to avoid data
  loss by assuming that a disc might need remounting if a certain time has
  elapsed since the last successful operation. To avoid a significant speed
  penalty from deselecting and reselecting cards, remounting isn't used for
  rapid back-to-back operations.
Admin:
  Already in use in RC12a.

Version 0.05. Tagged as 'SDFS-0_05'
parent 74212918
/* (0.04)
/* (0.05)
*
* This file is automatically maintained by srccommit, do not edit manually.
* Last processed by srccommit version: 1.1.
*
*/
#define Module_MajorVersion_CMHG 0.04
#define Module_MajorVersion_CMHG 0.05
#define Module_MinorVersion_CMHG
#define Module_Date_CMHG 29 Apr 2014
#define Module_Date_CMHG 14 Jul 2014
#define Module_MajorVersion "0.04"
#define Module_Version 4
#define Module_MajorVersion "0.05"
#define Module_Version 5
#define Module_MinorVersion ""
#define Module_Date "29 Apr 2014"
#define Module_Date "14 Jul 2014"
#define Module_ApplicationDate "29-Apr-14"
#define Module_ApplicationDate "14-Jul-14"
#define Module_ComponentName "SDFS"
#define Module_ComponentPath "cddl/RiscOS/Sources/FileSys/SDFS/SDFS"
#define Module_FullVersion "0.04"
#define Module_HelpVersion "0.04 (29 Apr 2014)"
#define Module_LibraryVersionInfo "0:4"
#define Module_FullVersion "0.05"
#define Module_HelpVersion "0.05 (14 Jul 2014)"
#define Module_LibraryVersionInfo "0:5"
......@@ -112,7 +112,7 @@ static low_level_error_t transfer_with_retries(uint32_t reason,
{
/* First deselect all cards; someone else may have been talking to another one in the
* same slot, and some cards don't like seeing a select without a preceding deselect */
COMMAND_NO_DATA(dr->bus, dr->slot, CMD7_SELECT_DESELECT_CARD, 0, R0, deselect_card_blk, e.oserror);
COMMAND_NO_DATA(dr->bus, dr->slot, flags & SDIOOp_DisableEscape, CMD7_SELECT_DESELECT_CARD, 0, R0, deselect_card_blk, e.oserror);
if (e.oserror)
dprintf("Deselect card returned %s\n", e.oserror->errmess);
if (e.oserror && e.oserror->errnum == ErrorNumber_Escape)
......@@ -124,7 +124,7 @@ static low_level_error_t transfer_with_retries(uint32_t reason,
if (!e.oserror)
{
/* Now select the card. This gives us an opportunity to detect if the card is locked */
COMMAND_NO_DATA(dr->bus, dr->slot, CMD7_SELECT_DESELECT_CARD, dr->rca << 16, R1, select_card_blk, e.oserror);
COMMAND_NO_DATA(dr->bus, dr->slot, flags & SDIOOp_DisableEscape, CMD7_SELECT_DESELECT_CARD, dr->rca << 16, R1, select_card_blk, e.oserror);
if (e.oserror)
dprintf("Select card returned %s\n", e.oserror->errmess);
if (e.oserror && e.oserror->errnum == ErrorNumber_Escape)
......@@ -151,7 +151,7 @@ static low_level_error_t transfer_with_retries(uint32_t reason,
tran_timeout += TRAN_TIMEOUT + 1;
while (!e.oserror)
{
COMMAND_NO_DATA(dr->bus, dr->slot, CMD13_SEND_STATUS, dr->rca << 16, R1, send_status_blk, e.oserror);
COMMAND_NO_DATA(dr->bus, dr->slot, flags & SDIOOp_DisableEscape, CMD13_SEND_STATUS, dr->rca << 16, R1, send_status_blk, e.oserror);
if (!e.oserror && (send_status_blk.response & R1_CURRENT_STATE_MASK) == R1_CURRENT_STATE_TRAN)
break;
int32_t now;
......@@ -176,7 +176,7 @@ static low_level_error_t transfer_with_retries(uint32_t reason,
/* On-the-wire block length is fixed as 512 bytes by SDHCI for memory access commands.
* Chances are that some cards out there have only been tested with SDHCI controllers,
* so it's best to stick to that size whatever controller we're using. */
COMMAND_NO_DATA(dr->bus, dr->slot, CMD16_SET_BLOCKLEN, SECTOR_SIZE, R1, set_blocklen_blk, e.oserror);
COMMAND_NO_DATA(dr->bus, dr->slot, flags & SDIOOp_DisableEscape, CMD16_SET_BLOCKLEN, SECTOR_SIZE, R1, set_blocklen_blk, e.oserror);
if (e.oserror)
dprintf("Set blocklen returned %s\n", e.oserror->errmess);
if (e.oserror && e.oserror->errnum == ErrorNumber_Escape)
......@@ -204,7 +204,7 @@ static low_level_error_t transfer_with_retries(uint32_t reason,
if (dr->cmd23_supported)
{
/* Card supports CMD23 - use it to improve speed */
COMMAND_NO_DATA(dr->bus, dr->slot, CMD23_SET_BLOCK_COUNT, *transfer_length >> LOG2_SECTOR_SIZE, R1, set_block_count_blk, e.oserror);
COMMAND_NO_DATA(dr->bus, dr->slot, flags & SDIOOp_DisableEscape, CMD23_SET_BLOCK_COUNT, *transfer_length >> LOG2_SECTOR_SIZE, R1, set_block_count_blk, e.oserror);
if (e.oserror)
{
dprintf("CMD23 error: %s\n", e.oserror->errmess);
......@@ -263,7 +263,7 @@ static low_level_error_t transfer_with_retries(uint32_t reason,
if (e.oserror)
{
/* SDIODriver's error buffer may be about to be overwritten, emsure we have a safe copy */
/* SDIODriver's error buffer may be about to be overwritten, ensure we have a safe copy */
if (e.oserror->errnum == ErrorNumber_Escape)
e.oserror = MESSAGE_ERRORLOOKUP(true, ExtEscape, 0);
else
......@@ -275,7 +275,7 @@ static low_level_error_t transfer_with_retries(uint32_t reason,
int32_t abort_retries = reason == DiscOp_Verify ? VERIFY_RETRIES : RETRIES;
do
{
COMMAND_NO_DATA(dr->bus, dr->slot, CMD12_STOP_TRANSMISSION, 0, R1b, stop_transmission_blk, abort_error);
COMMAND_NO_DATA(dr->bus, dr->slot, SDIOOp_DisableEscape, CMD12_STOP_TRANSMISSION, 0, R1b, stop_transmission_blk, abort_error);
/* No special case for Escape here - there's already a pending error, and we need to ensure the abort goes through */
}
while (abort_error && --abort_retries >= 0);
......@@ -405,6 +405,67 @@ low_level_error_t discop(uint32_t reason,
goto exit;
}
if (dr->slot_attached && dr->no_card_detect && dr->certainty == 0)
{
_kernel_oserror *err = _swix(SDIO_Control, _INR(0,1), SDIOControl_TryLock, (dr->bus << SDIOControl_BusShift) | (dr->slot << SDIOControl_SlotShift));
if (err)
{
if (err->errnum != ErrorNumber_SDIO_SlotInUse)
{
e.oserror = err;
dprintf("Slot lock returned %s\n", e.oserror->errmess);
goto exit;
}
/* otherwise the slot is currently in use, so obviously not in a timeout state */
}
else
{
dprintf("Need to probe for card presence\n");
bool rescan_needed = !dr->card_inserted;
if (dr->card_inserted)
{
COMMAND_NO_DATA(dr->bus, dr->slot, flags & SDIOOp_DisableEscape, CMD7_SELECT_DESELECT_CARD, 0, R0, deselect_card_blk, err);
if (err)
{
e.oserror = err->errnum == ErrorNumber_Escape ? MESSAGE_ERRORLOOKUP(true, ExtEscape, 0) : err;
dprintf("Deselect prior to probe returned %s\n", e.oserror->errmess);
_swix(SDIO_Control, _INR(0,1), SDIOControl_Unlock, (dr->bus << SDIOControl_BusShift) | (dr->slot << SDIOControl_SlotShift));
goto exit;
}
COMMAND_NO_DATA(dr->bus, dr->slot, flags & SDIOOp_DisableEscape, CMD7_SELECT_DESELECT_CARD, dr->rca << 16, R1, select_card_blk, err);
if (err)
{
if (err->errnum != ErrorNumber_SDIO_CTO)
{
e.oserror = err->errnum == ErrorNumber_Escape ? MESSAGE_ERRORLOOKUP(true, ExtEscape, 0) : err;
dprintf("Probe for RCA %04X returned %s\n", dr->rca, e.oserror->errmess);
_swix(SDIO_Control, _INR(0,1), SDIOControl_Unlock, (dr->bus << SDIOControl_BusShift) | (dr->slot << SDIOControl_SlotShift));
goto exit;
}
else
{
dprintf("Probe for RCA %04X met with no response\n", dr->rca);
rescan_needed = true;
}
}
else
dprintf("Probe for RCA %04X successful\n", dr->rca);
}
_swix(SDIO_Control, _INR(0,1), SDIOControl_Unlock, (dr->bus << SDIOControl_BusShift) | (dr->slot << SDIOControl_SlotShift));
if (rescan_needed)
{
/* Because we know we've already managed to acquire the lock, we know
* it's actually OK to do this, even though it's nominally non-reentrant */
dprintf("Rescan slot\n");
spinrw_read_unlock(&g_drive_lock); // we're going to want to claim a write lock on g_drive when we're re-entered
e.oserror = _swix(SDIO_Initialise, _INR(0,1), SDIOInitialise_RescanSlot, (dr->bus << SDIORescanSlot_BusShift) | (dr->slot << SDIORescanSlot_SlotShift));
spinrw_read_lock(&g_drive_lock);
if (e.oserror)
dprintf("Rescan slot returned %s\n", e.oserror->errmess);
}
}
}
if (!dr->slot_attached || !dr->card_inserted)
{
dprintf("Slot %sattached, card %sinserted\n", dr->slot_attached ? "" : "not ", dr->card_inserted ? "" : "not ");
......
......@@ -67,6 +67,18 @@ const char *message_lookup_direct(const char *token)
return e->errmess;
}
const char *message_lookup_buffer(const char *token, char *buffer, size_t buflen)
{
const char *result;
_kernel_oserror *e = _swix(MessageTrans_Lookup, _INR(0,3)|_OUT(2), &g_message_fd, token, buffer, buflen, &result);
/* Note that MessageTrans always null-terminates the result even if it's
* truncated, and the buffer length includes the terminator character. */
if (!e)
return result;
else
return e->errmess;
}
_kernel_oserror *message_copy(const _kernel_oserror *error)
{
m_ErrorBuf.errnum = error->errnum;
......
......@@ -67,19 +67,26 @@ void miscop_PollChanged(uint32_t drive, uint32_t * restrict sequence_number, uin
my_card_inserted &= g_drive[drive].card_inserted;
uint32_t my_sequence_number = g_drive[drive].sequence_number;
spin_unlock(&g_drive[drive].sequence_lock);
spin_lock(&g_drive[drive].certainty_lock);
uint32_t certain = g_drive[drive].certainty;
spin_unlock(&g_drive[drive].certainty_lock);
if (!g_drive[drive].slot_attached || !g_drive[drive].no_card_detect)
certain = 1;
spinrw_read_unlock(&g_drive_lock);
/* Now we have a consistent sequence number and inserted flag, compare it to
* the caller's world view. */
if (my_sequence_number == *sequence_number)
if (certain)
*result_flags = MiscOp_PollChanged_NotChanged_Flag | MiscOp_PollChanged_EmptyWorks_Flag | MiscOp_PollChanged_ChangedWorks_Flag;
else
*result_flags = MiscOp_PollChanged_MaybeChanged_Flag | MiscOp_PollChanged_EmptyWorks_Flag | MiscOp_PollChanged_ChangedWorks_Flag;
if (my_sequence_number != *sequence_number)
*result_flags = MiscOp_PollChanged_Changed_Flag | MiscOp_PollChanged_EmptyWorks_Flag | MiscOp_PollChanged_ChangedWorks_Flag;
if (!my_card_inserted)
if (!my_card_inserted && certain)
*result_flags = MiscOp_PollChanged_Empty_Flag | MiscOp_PollChanged_EmptyWorks_Flag | MiscOp_PollChanged_ChangedWorks_Flag;
*sequence_number = my_sequence_number;
dprintf("PollChanged - return flags %03X, sequence_number %u\n", *result_flags, *sequence_number);
dprintf("PollChanged(drive %u) - return flags %03X, sequence_number %u\n", drive, *result_flags, *sequence_number);
}
void miscop_LockDrive(uint32_t drive)
......
......@@ -37,6 +37,7 @@
#include "Global/FSNumbers.h"
#include "Global/OsBytes.h"
#include "Global/ModHand.h"
#include "Global/RISCOS.h"
#include "Global/SWIs.h"
#include "Interface/FileCore.h"
#include "Interface/FileCoreErr.h"
......@@ -93,11 +94,11 @@ _kernel_oserror *module_initialise(const char *cmd_tail, int podule_base, void *
gpiodebug_init();
/* Initialise global variables */
strncpy(g_media_type_name, message_lookup_direct("Card"), MEDIA_TYPE_NAME_LEN - 1);
g_media_type_name[MEDIA_TYPE_NAME_LEN - 1] = '\0';
message_lookup_buffer("Card", g_media_type_name, MEDIA_TYPE_NAME_LEN);
for (uint32_t i = 0; i < NUM_FLOPPIES + NUM_WINNIES; i++)
{
g_drive[i].sequence_lock = (spinlock_t) SPIN_INITIALISER;
g_drive[i].certainty_lock = (spinlock_t) SPIN_INITIALISER;
}
/* Register with Free */
......@@ -165,7 +166,8 @@ _kernel_oserror *module_initialise(const char *cmd_tail, int podule_base, void *
{
service_SDIOSlotAttached((slot_spec & SDIOEnumerate_BusMask) >> SDIOEnumerate_BusShift,
(slot_spec & SDIOEnumerate_SlotMask) >> SDIOEnumerate_SlotShift,
slot_spec & SDIOEnumerate_Integrated);
slot_spec & SDIOEnumerate_Integrated,
slot_spec & SDIOEnumerate_NoCardDetect);
uint32_t unit_handle = 0;
uint32_t unit_spec[2];
uint32_t unit_size[2];
......@@ -185,9 +187,14 @@ _kernel_oserror *module_initialise(const char *cmd_tail, int podule_base, void *
}
}
/* The module needs to be on TickerV the whole time */
e = _swix(OS_Claim, _INR(0,2), TickerV, module_tickerv_veneer, g_module_pw);
if (e) goto failed_init;
return NULL;
failed_init:
_swix(OS_Module, _INR(0,1), ModHandReason_Delete, "FileCore%" FILING_SYSTEM_TITLE);
_swix(Free_DeRegister, _INR(0,2), fsnumber_SDFS, free_veneer, &free_handle);
_swix(MessageTrans_CloseFile, _IN(0), &g_message_fd);
#ifndef ROM_MODULE
......@@ -202,6 +209,8 @@ _kernel_oserror *module_finalise(int fatal, int podule, void *pw)
IGNORE(podule);
IGNORE(pw);
_swix(OS_Release, _INR(0,2), TickerV, module_tickerv_veneer, g_module_pw);
/* Kill our supporting FileCore instantiation */
_swix(OS_Module, _INR(0,1), ModHandReason_Delete, "FileCore%" FILING_SYSTEM_TITLE);
......@@ -230,13 +239,15 @@ void module_service(int service_number, _kernel_swi_regs *r, void *pw)
case Service_SDIOSlotAttached:
service_SDIOSlotAttached((r->r[2] & SDIOSlotAttached_BusMask) >> SDIOSlotAttached_BusShift,
(r->r[2] & SDIOSlotAttached_SlotMask) >> SDIOSlotAttached_SlotShift,
r->r[2] & SDIOSlotAttached_Integrated);
r->r[2] & SDIOSlotAttached_Integrated,
r->r[2] & SDIOSlotAttached_NoCardDetect);
break;
case Service_SDIOSlotDetached:
service_SDIOSlotDetached((r->r[2] & SDIOSlotAttached_BusMask) >> SDIOSlotAttached_BusShift,
(r->r[2] & SDIOSlotAttached_SlotMask) >> SDIOSlotAttached_SlotShift,
r->r[2] & SDIOSlotAttached_Integrated);
r->r[2] & SDIOSlotAttached_Integrated,
r->r[2] & SDIOSlotAttached_NoCardDetect);
break;
case Service_SDIOUnitAttached:
......@@ -459,3 +470,24 @@ _kernel_oserror *module_discop_handler(_kernel_swi_regs *r, void *pw)
return (_kernel_oserror *) BadParmsErr;
}
}
int module_tickerv_handler(_kernel_swi_regs *r, void *pw)
{
IGNORE(r);
IGNORE(pw);
spinrw_read_lock(&g_drive_lock);
for (uint32_t drive = 0; drive < NUM_FLOPPIES + NUM_WINNIES; drive++)
{
spin_lock(&g_drive[drive].certainty_lock);
uint32_t old_value = g_drive[drive].certainty;
if (old_value > 0)
g_drive[drive].certainty = old_value - 1;
spin_unlock(&g_drive[drive].certainty_lock);
}
spinrw_read_unlock(&g_drive_lock);
return 1;
}
......@@ -49,7 +49,7 @@ static void upcall(uint32_t reason, uint8_t drive)
_swix(OS_UpCall, _INR(0,1), reason, drive_spec);
}
void service_SDIOSlotAttached(uint32_t bus, uint32_t slot, bool integrated)
void service_SDIOSlotAttached(uint32_t bus, uint32_t slot, bool integrated, bool no_card_detect)
{
/* Don't provide a drive for non-removable IO slots */
if (integrated)
......@@ -63,6 +63,7 @@ void service_SDIOSlotAttached(uint32_t bus, uint32_t slot, bool integrated)
break;
if (i < NUM_FLOPPIES + NUM_WINNIES)
{
g_drive[i].no_card_detect = no_card_detect;
g_drive[i].card_inserted = false;
g_drive[i].bus = bus;
g_drive[i].slot = slot;
......@@ -74,8 +75,10 @@ void service_SDIOSlotAttached(uint32_t bus, uint32_t slot, bool integrated)
spinrw_write_unlock(&g_drive_lock);
}
void service_SDIOSlotDetached(uint32_t bus, uint32_t slot, bool integrated)
void service_SDIOSlotDetached(uint32_t bus, uint32_t slot, bool integrated, bool no_card_detect)
{
IGNORE(no_card_detect);
/* Nothing to do for non-removable IO slots */
if (integrated)
return;
......@@ -165,6 +168,7 @@ void service_SDIOUnitAttached(uint32_t bus, uint32_t slot, uint32_t rca, uint32_
dprintf("Allocate additional drive %u for bus %u / slot %u\n", i, bus, slot);
}
}
dprintf("Drive %u timeout reset due to insertion; sequence %u inserted %u\n", i, g_drive[i].sequence_number, g_drive[i].card_inserted);
if (i < NUM_FLOPPIES + NUM_WINNIES && !g_drive[i].card_inserted)
{
g_drive[i].write_protected = writeprotect;
......@@ -173,6 +177,9 @@ void service_SDIOUnitAttached(uint32_t bus, uint32_t slot, uint32_t rca, uint32_
g_drive[i].mmc = mmc;
g_drive[i].rca = rca;
barrier(); /* because we may read these from the background */
spin_lock(&g_drive[i].certainty_lock);
g_drive[i].certainty = FAITH;
spin_unlock(&g_drive[i].certainty_lock);
spin_lock(&g_drive[i].sequence_lock);
g_drive[i].card_inserted = true;
++g_drive[i].sequence_number;
......@@ -255,6 +262,9 @@ void service_SDIOUnitDetached(uint32_t bus, uint32_t slot, uint32_t rca, uint32_
* can be issued from the background. Instead, we need to be very careful about
* the ordering which we test things, and insert memory barriers. */
dprintf("Removal: drive 0 attached %u inserted %u bus %u slot %u rca %04X; compare %u/%u/%04X; seqno %u\n",
g_drive[0].slot_attached, g_drive[0].card_inserted, g_drive[0].bus, g_drive[0].slot, g_drive[0].rca,
bus, slot, rca, g_drive[0].sequence_number);
uint32_t i;
for (i = 0; i < NUM_FLOPPIES + NUM_WINNIES; i++)
{
......@@ -266,6 +276,9 @@ void service_SDIOUnitDetached(uint32_t bus, uint32_t slot, uint32_t rca, uint32_
barrier();
if (g_drive[i].bus == bus && g_drive[i].slot == slot && g_drive[i].rca == rca)
{
spin_lock(&g_drive[i].certainty_lock);
g_drive[i].certainty = FAITH;
spin_unlock(&g_drive[i].certainty_lock);
spin_lock(&g_drive[i].sequence_lock);
g_drive[i].card_inserted = false;
++g_drive[i].sequence_number;
......@@ -313,6 +326,11 @@ void service_SDIOSlotReleased(uint32_t bus, uint32_t slot)
}
}
}
if (g_drive[i].bus == bus && g_drive[i].slot == slot)
{
dprintf("Slot attached to drive %u being released, so reset timeout\n", i);
g_drive[i].certainty = FAITH;
}
}
}
}
......@@ -52,3 +52,5 @@ date-string: Module_Date_CMHG
generic-veneers: module_discop_veneer/module_discop_handler,
module_miscop_veneer/module_miscop_handler
vector-handlers: module_tickerv_veneer/module_tickerv_handler
......@@ -85,6 +85,9 @@
//#define VERIFY_RETRIES (1) /* same as ADFS uses for hard discs */
#define VERIFY_RETRIES (4)
/** Timeout for transition to disc-maybe-changed state, in cs */
#define FAITH (100)
/** Bit shift to convert between bytes and sectors */
#define LOG2_SECTOR_SIZE (9)
......@@ -112,7 +115,7 @@
/** 3-way concatenation macro that expands the result of the concatenation. */
#define CONCAT3_AND_EXPAND(a,b,c) CONCAT(a,b,c)
/** Issue a foreground command with no data transfer by jumping to the SDIO_Op SWI handler.
/** Issue a foreground command with no data transfer by calling the SDIO_Op SWI handler.
* \param bus Bus index.
* \param slot Slot index.
* \param cmd Command to issue, including application-command bit and flags if appropriate.
......@@ -121,14 +124,15 @@
* \param crblock Name of command-response block to declare. Data type is derived from \a res_type, and block remains in scope after the macro.
* \param error Name of variable to hold error returned.
*/
#define COMMAND_NO_DATA(bus, slot, cmd, arg, res_type, crblock, error) \
#define COMMAND_NO_DATA(bus, slot, escape_flag, cmd, arg, res_type, crblock, error) \
CONCAT3(sdioop_cmdres_,res_type,_t) crblock; \
crblock.command = (cmd); \
crblock.argument = (arg); \
(error) = sdio_op_fg_nodata(((slot) << SDIOOp_SlotShift) | \
((bus) << SDIOOp_BusShift) | \
CONCAT_AND_EXPAND(SDIOOp_,res_type) | \
SDIOOp_TransNone, \
SDIOOp_TransNone | \
(escape_flag), \
8 + CONCAT_AND_EXPAND(SDIOOp_ResLen_,res_type), \
&crblock, \
OP_TIMEOUT);
......@@ -230,6 +234,7 @@ typedef PACKED(struct)
typedef struct
{
bool slot_attached; /**< Do we have an SDIODriver slot associated with this drive? */
bool no_card_detect; /**< Does the attached SDIODriver slot have a broken card detect? */
volatile bool card_inserted; /**< Is a memory card present? */
bool write_protected; /**< Is the write-protect tab engaged? */
bool memory_card; /**< Is is a memory card? */
......@@ -252,6 +257,8 @@ typedef struct
uint64_t capacity; /**< Card size, in sectors */
volatile uint32_t sequence_number; /**< FileCore disc detection sequence number */
spinlock_t sequence_lock; /**< Ensures updates to card_inserted and sequence_number are consistent */
volatile uint32_t certainty; /**< Countdown until we lose confidence in what's in the drive (for drives with faulty card detect) */
spinlock_t certainty_lock; /**< Ensures atomic updates of certainty */
} drive_t;
......
......@@ -34,6 +34,7 @@
_kernel_oserror *message_error_lookup(bool local, uint32_t number, const char *name, ...);
const char *message_lookup_direct(const char *token);
const char *message_lookup_buffer(const char *token, char *buffer, size_t buflen);
_kernel_oserror *message_copy(const _kernel_oserror *error);
#endif
......@@ -30,8 +30,8 @@
#include <stdbool.h>
#include "kernel.h"
void service_SDIOSlotAttached(uint32_t bus, uint32_t slot, bool integrated);
void service_SDIOSlotDetached(uint32_t bus, uint32_t slot, bool integrated);
void service_SDIOSlotAttached(uint32_t bus, uint32_t slot, bool integrated, bool no_card_detect);
void service_SDIOSlotDetached(uint32_t bus, uint32_t slot, bool integrated, bool no_card_detect);
void service_SDIOUnitAttached(uint32_t bus, uint32_t slot, uint32_t rca, uint32_t unit, uint32_t fic, bool writeprotect, bool mmc, uint64_t capacity);
void service_SDIOUnitDetached(uint32_t bus, uint32_t slot, uint32_t rca, uint32_t unit, uint32_t fic, bool writeprotect, bool mmc);
void service_SDIOSlotReleased(uint32_t bus, uint32_t slot);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment