Commit 7592adfe authored by Ben Avison's avatar Ben Avison
Browse files

Add Raspberry Pi Compute module support

Detail:
  The eMMC chip on the Compute module is now treated as a hard drive by SDFS.
  A number of bugs (relating to top-bit-set disc addresses for example) were
  required to facilitate this. If a board has an eMMC chip, then the default
  SDFS drive is drive 4 rather than drive 0; this doesn't require any change
  to the default CMOS values in the kernel or HAL (SDFS adjusts its
  interpretation of the CMOS byte instead).
Admin:
  Tested on a Compute module (of course).

Version 0.07. Tagged as 'SDFS-0_07'
parent 8683288a
/* (0.06)
/* (0.07)
*
* This file is automatically maintained by srccommit, do not edit manually.
* Last processed by srccommit version: 1.1.
*
*/
#define Module_MajorVersion_CMHG 0.06
#define Module_MajorVersion_CMHG 0.07
#define Module_MinorVersion_CMHG
#define Module_Date_CMHG 31 Oct 2014
#define Module_Date_CMHG 02 Feb 2015
#define Module_MajorVersion "0.06"
#define Module_Version 6
#define Module_MajorVersion "0.07"
#define Module_Version 7
#define Module_MinorVersion ""
#define Module_Date "31 Oct 2014"
#define Module_Date "02 Feb 2015"
#define Module_ApplicationDate "31-Oct-14"
#define Module_ApplicationDate "02-Feb-15"
#define Module_ComponentName "SDFS"
#define Module_ComponentPath "cddl/RiscOS/Sources/FileSys/SDFS/SDFS"
#define Module_FullVersion "0.06"
#define Module_HelpVersion "0.06 (31 Oct 2014)"
#define Module_LibraryVersionInfo "0:6"
#define Module_FullVersion "0.07"
#define Module_HelpVersion "0.07 (02 Feb 2015)"
#define Module_LibraryVersionInfo "0:7"
......@@ -60,7 +60,7 @@ _kernel_oserror *command_status_sdfsdrive(void)
{
uint32_t default_drive;
_swix(OS_Byte, _INR(0,1)|_OUT(2), OsByte_ReadCMOS, DEFAULT_DRIVE_BYTE, &default_drive);
default_drive = (default_drive & DEFAULT_DRIVE_MASK) >> DEFAULT_DRIVE_SHIFT;
default_drive = ((default_drive & DEFAULT_DRIVE_MASK) >> DEFAULT_DRIVE_SHIFT) ^ g_default_drive_toggle;
printf("SDFSdrive %u\n", default_drive);
return NULL;
}
......@@ -84,7 +84,7 @@ _kernel_oserror *command_configure_sdfsdrive(const char *drive)
return configure_TOO_LARGE;
_swix(OS_Byte, _INR(0,1)|_OUT(2), OsByte_ReadCMOS, DEFAULT_DRIVE_BYTE, &cmos);
cmos = cmos &~ DEFAULT_DRIVE_MASK;
cmos |= default_drive << DEFAULT_DRIVE_SHIFT;
cmos |= (default_drive ^ g_default_drive_toggle) << DEFAULT_DRIVE_SHIFT;
_swix(OS_Byte, _INR(0,2), OsByte_WriteCMOS, DEFAULT_DRIVE_BYTE, cmos);
return NULL;
}
......@@ -37,3 +37,4 @@ void (*g_filecore_callback_winnie_op_completed)(void);
char g_media_type_name[MEDIA_TYPE_NAME_LEN];
drive_t g_drive[NUM_FLOPPIES + NUM_WINNIES];
spinrwlock_t g_drive_lock = SPINRW_INITIALISER;
uint8_t g_default_drive_toggle;
......@@ -43,6 +43,7 @@
#include "Interface/FileCoreErr.h"
#include "Interface/SDFSErr.h"
#include "Interface/SDIO.h"
#include "Interface/SDHCIDevice.h"
#include "SyncLib/synclib.h"
......@@ -113,9 +114,37 @@ _kernel_oserror *module_initialise(const char *cmd_tail, int podule_base, void *
goto failed_init;
}
/* Some machines (such as the Compute Module) have non-removable eMMC or eSD
* so the natural default drive is 4, but they run the same ROM as machines for
* which the natural default drive is 0. Solve this by inverting bit 2 of the
* CMOS if there is a HAL device with the IntegratedMem flag set. We can't ask
* SDIODriver because that would have to wait until callbacks have triggered.
*/
uint32_t handle = 0;
while (true)
{
sdhcidevice_t *device;
uint32_t sloti;
_kernel_oserror *e = _swix(OS_Hardware, _INR(0,1)|_IN(8)|_OUTR(1,2),
HALDeviceType_ExpCtl + HALDeviceExpCtl_SDIO,
handle, 5, &handle, &device);
if (e != NULL || handle == -1u)
break;
for (sloti = 0; sloti < device->slots; sloti++)
{
if (device->slotinfo[sloti].flags & HALDeviceSDHCI_SlotFlag_IntegratedMem)
break;
}
if (sloti < device->slots)
{
g_default_drive_toggle = 4;
break;
}
}
/* Read default drive from CMOS byte 17, bits 4-6 */
_swix(OS_Byte, _INR(0,1)|_OUT(2), OsByte_ReadCMOS, DEFAULT_DRIVE_BYTE, &default_drive);
default_drive = (default_drive & DEFAULT_DRIVE_MASK) >> DEFAULT_DRIVE_SHIFT;
default_drive = ((default_drive & DEFAULT_DRIVE_MASK) >> DEFAULT_DRIVE_SHIFT) ^ g_default_drive_toggle;
/* Register with FileCore */
e = _swix(FileCore_Create, _INR(0,6)|_OUTR(0,2),
......@@ -167,7 +196,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_NoCardDetect);
slot_spec & SDIOEnumerate_NoCardDetect,
slot_spec & SDIOEnumerate_IntegratedMem);
uint32_t unit_handle = 0;
uint32_t unit_spec[2];
uint32_t unit_size[2];
......@@ -240,14 +270,16 @@ void module_service(int service_number, _kernel_swi_regs *r, void *pw)
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_NoCardDetect);
r->r[2] & SDIOSlotAttached_NoCardDetect,
r->r[2] & SDIOSlotAttached_IntegratedMem);
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_NoCardDetect);
r->r[2] & SDIOSlotAttached_NoCardDetect,
r->r[2] & SDIOSlotAttached_IntegratedMem);
break;
case Service_SDIOUnitAttached:
......@@ -422,7 +454,7 @@ _kernel_oserror *module_discop_handler(_kernel_swi_regs *r, void *pw)
dprintf("DiscOp %u, flags %03X, disc address %u/%08X, buffer %08X, length %u\n",
r->r[1] & DiscOp_Op_Mask,
r->r[1] &~ DiscOp_Op_Mask,
r->r[2] >> 28,
(uint32_t) r->r[2] >> 28,
r->r[2] &~ 0xE0000000,
r->r[3],
r->r[4]);
......@@ -445,7 +477,7 @@ _kernel_oserror *module_discop_handler(_kernel_swi_regs *r, void *pw)
* least in the SectorDiscOp world */
return (_kernel_oserror *) BadParmsErr;
e = discop(reason, flags,
r->r[2] >> LegacyDiscAddress_DriveNumber_Shift, &disc_address,
(uint32_t) r->r[2] >> LegacyDiscAddress_DriveNumber_Shift, &disc_address,
(block_or_scatter_t *) &r->r[3], (size_t *) &r->r[4]
).oserror;
r->r[2] = (r->r[2] &~ LegacyDiscAddress_SectorOffset_Mask) | (uint32_t) (disc_address >> LOG2_SECTOR_SIZE);
......
......@@ -49,19 +49,22 @@ 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, bool no_card_detect)
void service_SDIOSlotAttached(uint32_t bus, uint32_t slot, bool integrated, bool no_card_detect, bool integrated_mem)
{
/* Don't provide a drive for non-removable IO slots */
if (integrated)
return;
uint32_t min_drive = integrated_mem ? 4 : 0;
uint32_t max_drive = min_drive + (integrated_mem ? NUM_WINNIES : NUM_FLOPPIES) - 1;
/* We need at least one drive to represent this new slot */
spinrw_write_lock(&g_drive_lock);
uint32_t i;
for (i = 0; i < NUM_FLOPPIES + NUM_WINNIES; i++)
for (i = min_drive; i <= max_drive; i++)
if (!g_drive[i].slot_attached)
break;
if (i < NUM_FLOPPIES + NUM_WINNIES)
if (i <= max_drive)
{
g_drive[i].no_card_detect = no_card_detect;
g_drive[i].card_inserted = false;
......@@ -75,9 +78,10 @@ void service_SDIOSlotAttached(uint32_t bus, uint32_t slot, bool integrated, bool
spinrw_write_unlock(&g_drive_lock);
}
void service_SDIOSlotDetached(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, bool integrated_mem)
{
IGNORE(no_card_detect);
IGNORE(integrated_mem);
/* Nothing to do for non-removable IO slots */
if (integrated)
......@@ -162,7 +166,7 @@ void service_SDIOUnitAttached(uint32_t bus, uint32_t slot, uint32_t rca, uint32_
break;
if (i == NUM_FLOPPIES + NUM_WINNIES)
{
/* Look for a empty drive associated with this slot. */
/* Look for an empty drive associated with this slot. */
for (i = 0; i < NUM_FLOPPIES + NUM_WINNIES; i++)
if (g_drive[i].slot_attached && !g_drive[i].card_inserted && g_drive[i].bus == bus && g_drive[i].slot == slot)
break;
......@@ -170,10 +174,29 @@ void service_SDIOUnitAttached(uint32_t bus, uint32_t slot, uint32_t rca, uint32_
{
/* There weren't any empty drives for this slot.
* See if we can allocate another. */
for (i = 0; i < NUM_FLOPPIES + NUM_WINNIES; i++)
uint32_t min_drive = 0;
uint32_t max_drive = NUM_FLOPPIES - 1;
uint32_t slot_handle = 0;
uint32_t slot_spec;
while (!_swix(SDIO_Enumerate, _INR(0,1)|_OUTR(1,2),
SDIOEnumerate_Slots, slot_handle,
&slot_handle, &slot_spec) && slot_handle != 0)
{
if ((slot_spec & SDIOEnumerate_BusMask) >> SDIOEnumerate_BusShift == bus &&
(slot_spec & SDIOEnumerate_SlotMask) >> SDIOEnumerate_SlotShift == slot)
{
if (slot_spec & SDIOEnumerate_IntegratedMem)
{
min_drive = 4;
max_drive = 4 + NUM_WINNIES - 1;
}
break;
}
}
for (i = min_drive; i <= max_drive; i++)
if (!g_drive[i].slot_attached)
break;
if (i < NUM_FLOPPIES + NUM_WINNIES)
if (i <= max_drive)
{
/* Multiple drives for this slot */
g_drive[i].card_inserted = false;
......@@ -183,6 +206,8 @@ void service_SDIOUnitAttached(uint32_t bus, uint32_t slot, uint32_t rca, uint32_
g_drive[i].slot_attached = true;
dprintf("Allocate additional drive %u for bus %u / slot %u\n", i, bus, slot);
}
else
i = NUM_FLOPPIES + NUM_WINNIES;
}
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)
......
......@@ -73,7 +73,7 @@
#define NUM_FLOPPIES (4)
/** Number of "hard" drives to declare to FileCore */
#define NUM_WINNIES (0)
#define NUM_WINNIES (1)
/** Buffer size for media type name */
#define MEDIA_TYPE_NAME_LEN (20)
......@@ -291,5 +291,8 @@ extern drive_t g_drive[NUM_FLOPPIES + NUM_WINNIES];
/** Lock for drive state array */
extern spinrwlock_t g_drive_lock;
/** Bitmask to invert in default drive number in CMOS */
extern uint8_t g_default_drive_toggle;
#endif
......@@ -30,8 +30,8 @@
#include <stdbool.h>
#include "kernel.h"
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_SDIOSlotAttached(uint32_t bus, uint32_t slot, bool integrated, bool no_card_detect, bool integrated_mem);
void service_SDIOSlotDetached(uint32_t bus, uint32_t slot, bool integrated, bool no_card_detect, bool integrated_mem);
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