c7cbd494eb
Change-Id: If84f8a2e35172be4b2ae7cd105b3975b587acd6c
825 lines
19 KiB
C
825 lines
19 KiB
C
/***************************************************************************
|
|
* __________ __ ___.
|
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
|
* \/ \/ \/ \/ \/
|
|
* $Id$
|
|
*
|
|
* Copyright (C) 2008 by Frank Gevaerts
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
|
* KIND, either express or implied.
|
|
*
|
|
****************************************************************************/
|
|
#include "storage.h"
|
|
#include "kernel.h"
|
|
#include "ata_idle_notify.h"
|
|
#include "usb.h"
|
|
#include "disk.h"
|
|
|
|
#ifdef CONFIG_STORAGE_MULTI
|
|
|
|
#define DRIVER_MASK 0xff000000
|
|
#define DRIVER_OFFSET 24
|
|
#define DRIVE_MASK 0x00ff0000
|
|
#define DRIVE_OFFSET 16
|
|
#define PARTITION_MASK 0x0000ff00
|
|
|
|
static unsigned int storage_drivers[NUM_DRIVES];
|
|
static unsigned int num_drives;
|
|
#endif /* CONFIG_STORAGE_MULTI */
|
|
|
|
/* defaults: override elsewhere target-wise if they must be different */
|
|
#if (CONFIG_STORAGE & STORAGE_ATA)
|
|
#ifndef ATA_THREAD_STACK_SIZE
|
|
#define ATA_THREAD_STACK_SIZE (DEFAULT_STACK_SIZE*2)
|
|
#endif
|
|
#endif
|
|
#if (CONFIG_STORAGE & STORAGE_MMC)
|
|
#ifndef MMC_THREAD_STACK_SIZE
|
|
#define MMC_THREAD_STACK_SIZE (DEFAULT_STACK_SIZE*2)
|
|
#endif
|
|
#endif
|
|
#if (CONFIG_STORAGE & STORAGE_SD)
|
|
#ifndef SD_THREAD_STACK_SIZE
|
|
#define SD_THREAD_STACK_SIZE (DEFAULT_STACK_SIZE*2)
|
|
#endif
|
|
#endif
|
|
#if (CONFIG_STORAGE & STORAGE_NAND)
|
|
#ifndef NAND_THREAD_STACK_SIZE
|
|
#define NAND_THREAD_STACK_SIZE (DEFAULT_STACK_SIZE*2)
|
|
#endif
|
|
#endif
|
|
#if (CONFIG_STORAGE & STORAGE_RAMDISK)
|
|
#ifndef RAMDISK_THREAD_STACK_SIZE
|
|
#define RAMDISK_THREAD_STACK_SIZE (0) /* not used on its own */
|
|
#endif
|
|
#endif
|
|
|
|
static struct event_queue storage_queue SHAREDBSS_ATTR;
|
|
static unsigned int storage_thread_id = 0;
|
|
|
|
static union {
|
|
#if (CONFIG_STORAGE & STORAGE_ATA)
|
|
long stk_ata[ATA_THREAD_STACK_SIZE / sizeof (long)];
|
|
#endif
|
|
#if (CONFIG_STORAGE & STORAGE_MMC)
|
|
long stk_mmc[MMC_THREAD_STACK_SIZE / sizeof (long)];
|
|
#endif
|
|
#if (CONFIG_STORAGE & STORAGE_SD)
|
|
long stk_sd[SD_THREAD_STACK_SIZE / sizeof (long)];
|
|
#endif
|
|
#if (CONFIG_STORAGE & STORAGE_NAND)
|
|
long stk_nand[NAND_THREAD_STACK_SIZE / sizeof (long)];
|
|
#endif
|
|
#if (CONFIG_STORAGE & STORAGE_RAMDISK)
|
|
long stk_ramdisk[RAMDISK_THREAD_STACK_SIZE / sizeof (long)];
|
|
#endif
|
|
} storage_thread_stack;
|
|
|
|
static const char storage_thread_name[] =
|
|
#if (CONFIG_STORAGE & STORAGE_ATA)
|
|
"/ata"
|
|
#endif
|
|
#if (CONFIG_STORAGE & STORAGE_MMC)
|
|
"/mmc"
|
|
#endif
|
|
#if (CONFIG_STORAGE & STORAGE_SD)
|
|
"/sd"
|
|
#endif
|
|
#if (CONFIG_STORAGE & STORAGE_NAND)
|
|
"/nand"
|
|
#endif
|
|
#if (CONFIG_STORAGE & STORAGE_RAMDISK)
|
|
"/ramdisk"
|
|
#endif
|
|
;
|
|
|
|
/* event is targeted to a specific drive */
|
|
#define DRIVE_EVT (1 << STORAGE_NUM_TYPES)
|
|
|
|
#ifdef CONFIG_STORAGE_MULTI
|
|
static int storage_event_send(unsigned int route, long id, intptr_t data)
|
|
{
|
|
/* most events go to everyone */
|
|
if (UNLIKELY(route == DRIVE_EVT)) {
|
|
route = (storage_drivers[data] & DRIVER_MASK) >> DRIVER_OFFSET;
|
|
data = (storage_drivers[data] & DRIVE_MASK) >> DRIVE_OFFSET;
|
|
}
|
|
|
|
int rc = 0;
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_ATA)
|
|
if (route & STORAGE_ATA) {
|
|
rc = ata_event(id, data);
|
|
}
|
|
#endif
|
|
#if (CONFIG_STORAGE & STORAGE_MMC)
|
|
if (route & STORAGE_MMC) {
|
|
rc = mmc_event(id, data);
|
|
}
|
|
#endif
|
|
#if (CONFIG_STORAGE & STORAGE_SD)
|
|
if (route & STORAGE_SD) {
|
|
rc = sd_event(id, data);
|
|
}
|
|
#endif
|
|
#if (CONFIG_STORAGE & STORAGE_NAND)
|
|
if (route & STORAGE_NAND) {
|
|
rc = nand_event(id, data);
|
|
}
|
|
#endif
|
|
#if (CONFIG_STORAGE & STORAGE_RAMDISK)
|
|
if (route & STORAGE_RAMDISK) {
|
|
rc = ramdisk_event(id, data);
|
|
}
|
|
#endif
|
|
|
|
return rc;
|
|
}
|
|
#endif /* CONFIG_STORAGE_MULTI */
|
|
|
|
#ifndef CONFIG_STORAGE_MULTI
|
|
static FORCE_INLINE int storage_event_send(unsigned int route, long id,
|
|
intptr_t data)
|
|
{
|
|
return route ? STORAGE_FUNCTION(event)(id, data) : 0;
|
|
}
|
|
#endif /* ndef CONFIG_STORAGE_MULTI */
|
|
|
|
static void NORETURN_ATTR storage_thread(void)
|
|
{
|
|
unsigned int bdcast = CONFIG_STORAGE;
|
|
bool usb_mode = false;
|
|
struct queue_event ev;
|
|
|
|
while (1)
|
|
{
|
|
queue_wait_w_tmo(&storage_queue, &ev, HZ/2);
|
|
|
|
switch (ev.id)
|
|
{
|
|
case SYS_TIMEOUT:;
|
|
/* drivers hold their bit low when they want to
|
|
sleep and keep it high otherwise */
|
|
unsigned int trig = 0;
|
|
storage_event_send(bdcast, Q_STORAGE_TICK, (intptr_t)&trig);
|
|
trig = bdcast & ~trig;
|
|
if (trig) {
|
|
if (!usb_mode) {
|
|
call_storage_idle_notifys(false);
|
|
}
|
|
storage_event_send(trig, Q_STORAGE_SLEEPNOW, 0);
|
|
}
|
|
break;
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_ATA)
|
|
case Q_STORAGE_SLEEP:
|
|
storage_event_send(bdcast, ev.id, 0);
|
|
break;
|
|
#endif
|
|
|
|
#ifdef STORAGE_CLOSE
|
|
case Q_STORAGE_CLOSE:
|
|
storage_event_send(CONFIG_STORAGE, ev.id, 0);
|
|
thread_exit();
|
|
#endif /* STORAGE_CLOSE */
|
|
|
|
#ifdef HAVE_HOTSWAP
|
|
case SYS_HOTSWAP_INSERTED:
|
|
case SYS_HOTSWAP_EXTRACTED:
|
|
if (!usb_mode) {
|
|
int drive = IF_MD_DRV(ev.data);
|
|
if (!CHECK_DRV(drive)) {
|
|
break;
|
|
}
|
|
|
|
int umnt = disk_unmount(drive);
|
|
int mnt = 0;
|
|
int rci = storage_event_send(DRIVE_EVT, ev.id, drive);
|
|
|
|
if (ev.id == SYS_HOTSWAP_INSERTED && !rci) {
|
|
mnt = disk_mount(drive);
|
|
}
|
|
|
|
if (umnt > 0 || mnt > 0) {
|
|
/* something was unmounted and/or mounted */
|
|
queue_broadcast(SYS_FS_CHANGED, drive);
|
|
}
|
|
}
|
|
break;
|
|
#endif /* HAVE_HOTSWAP */
|
|
|
|
#ifndef USB_NONE
|
|
case SYS_USB_CONNECTED:
|
|
case SYS_USB_DISCONNECTED:
|
|
bdcast = 0;
|
|
storage_event_send(CONFIG_STORAGE, ev.id, (intptr_t)&bdcast);
|
|
usb_mode = ev.id == SYS_USB_CONNECTED;
|
|
if (usb_mode) {
|
|
usb_acknowledge(SYS_USB_CONNECTED_ACK);
|
|
}
|
|
else {
|
|
bdcast = CONFIG_STORAGE;
|
|
}
|
|
break;
|
|
#endif /* ndef USB_NONE */
|
|
}
|
|
}
|
|
}
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_ATA)
|
|
void storage_sleep(void)
|
|
{
|
|
if (storage_thread_id) {
|
|
queue_post(&storage_queue, Q_STORAGE_SLEEP, 0);
|
|
}
|
|
}
|
|
#endif /* (CONFIG_STORAGE & STORAGE_ATA) */
|
|
|
|
#ifdef STORAGE_CLOSE
|
|
void storage_close(void)
|
|
{
|
|
if (storage_thread_id) {
|
|
queue_post(&storage_queue, Q_STORAGE_CLOSE, 0);
|
|
thread_wait(storage_thread_id);
|
|
}
|
|
}
|
|
#endif /* STORAGE_CLOSE */
|
|
|
|
static inline void storage_thread_init(void)
|
|
{
|
|
if (storage_thread_id) {
|
|
return;
|
|
}
|
|
|
|
queue_init(&storage_queue, true);
|
|
storage_thread_id = create_thread(storage_thread, &storage_thread_stack,
|
|
sizeof (storage_thread_stack),
|
|
0, &storage_thread_name[1]
|
|
IF_PRIO(, PRIORITY_USER_INTERFACE)
|
|
IF_COP(, CPU));
|
|
}
|
|
|
|
int storage_init(void)
|
|
{
|
|
int rc=0;
|
|
|
|
#ifdef CONFIG_STORAGE_MULTI
|
|
int i;
|
|
num_drives=0;
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_ATA)
|
|
if ((rc=ata_init())) return rc;
|
|
|
|
int ata_drives = ata_num_drives(num_drives);
|
|
for (i=0; i<ata_drives; i++)
|
|
{
|
|
storage_drivers[num_drives++] =
|
|
(STORAGE_ATA<<DRIVER_OFFSET) | (i << DRIVE_OFFSET);
|
|
}
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_MMC)
|
|
if ((rc=mmc_init())) return rc;
|
|
|
|
int mmc_drives = mmc_num_drives(num_drives);
|
|
for (i=0; i<mmc_drives ;i++)
|
|
{
|
|
storage_drivers[num_drives++] =
|
|
(STORAGE_MMC<<DRIVER_OFFSET) | (i << DRIVE_OFFSET);
|
|
}
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_SD)
|
|
if ((rc=sd_init())) return rc;
|
|
|
|
int sd_drives = sd_num_drives(num_drives);
|
|
for (i=0; i<sd_drives; i++)
|
|
{
|
|
storage_drivers[num_drives++] =
|
|
(STORAGE_SD<<DRIVER_OFFSET) | (i << DRIVE_OFFSET);
|
|
}
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_NAND)
|
|
if ((rc=nand_init())) return rc;
|
|
|
|
int nand_drives = nand_num_drives(num_drives);
|
|
for (i=0; i<nand_drives; i++)
|
|
{
|
|
storage_drivers[num_drives++] =
|
|
(STORAGE_NAND<<DRIVER_OFFSET) | (i << DRIVE_OFFSET);
|
|
}
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_RAMDISK)
|
|
if ((rc=ramdisk_init())) return rc;
|
|
|
|
int ramdisk_drives = ramdisk_num_drives(num_drives);
|
|
for (i=0; i<ramdisk_drives; i++)
|
|
{
|
|
storage_drivers[num_drives++] =
|
|
(STORAGE_RAMDISK<<DRIVER_OFFSET) | (i << DRIVE_OFFSET);
|
|
}
|
|
#endif
|
|
#else /* ndef CONFIG_STORAGE_MULTI */
|
|
rc = STORAGE_FUNCTION(init)();
|
|
#endif /* CONFIG_STORAGE_MULTI */
|
|
|
|
storage_thread_init();
|
|
return rc;
|
|
}
|
|
|
|
int storage_read_sectors(IF_MD(int drive,) unsigned long start, int count,
|
|
void* buf)
|
|
{
|
|
#ifdef CONFIG_STORAGE_MULTI
|
|
int driver=(storage_drivers[drive] & DRIVER_MASK)>>DRIVER_OFFSET;
|
|
int ldrive=(storage_drivers[drive] & DRIVE_MASK)>>DRIVE_OFFSET;
|
|
|
|
switch (driver)
|
|
{
|
|
#if (CONFIG_STORAGE & STORAGE_ATA)
|
|
case STORAGE_ATA:
|
|
return ata_read_sectors(IF_MD(ldrive,) start,count,buf);
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_MMC)
|
|
case STORAGE_MMC:
|
|
return mmc_read_sectors(IF_MD(ldrive,) start,count,buf);
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_SD)
|
|
case STORAGE_SD:
|
|
return sd_read_sectors(IF_MD(ldrive,) start,count,buf);
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_NAND)
|
|
case STORAGE_NAND:
|
|
return nand_read_sectors(IF_MD(ldrive,) start,count,buf);
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_RAMDISK)
|
|
case STORAGE_RAMDISK:
|
|
return ramdisk_read_sectors(IF_MD(ldrive,) start,count,buf);
|
|
#endif
|
|
}
|
|
|
|
return -1;
|
|
#else /* CONFIG_STORAGE_MULTI */
|
|
return STORAGE_FUNCTION(read_sectors)(IF_MD(drive,)start,count,buf);
|
|
#endif /* CONFIG_STORAGE_MULTI */
|
|
|
|
}
|
|
|
|
int storage_write_sectors(IF_MD(int drive,) unsigned long start, int count,
|
|
const void* buf)
|
|
{
|
|
#ifdef CONFIG_STORAGE_MULTI
|
|
int driver=(storage_drivers[drive] & DRIVER_MASK)>>DRIVER_OFFSET;
|
|
int ldrive=(storage_drivers[drive] & DRIVE_MASK)>>DRIVE_OFFSET;
|
|
|
|
switch (driver)
|
|
{
|
|
#if (CONFIG_STORAGE & STORAGE_ATA)
|
|
case STORAGE_ATA:
|
|
return ata_write_sectors(IF_MD(ldrive,)start,count,buf);
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_MMC)
|
|
case STORAGE_MMC:
|
|
return mmc_write_sectors(IF_MD(ldrive,)start,count,buf);
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_SD)
|
|
case STORAGE_SD:
|
|
return sd_write_sectors(IF_MD(ldrive,)start,count,buf);
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_NAND)
|
|
case STORAGE_NAND:
|
|
return nand_write_sectors(IF_MD(ldrive,)start,count,buf);
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_RAMDISK)
|
|
case STORAGE_RAMDISK:
|
|
return ramdisk_write_sectors(IF_MD(ldrive,)start,count,buf);
|
|
#endif
|
|
}
|
|
|
|
return -1;
|
|
#else /* CONFIG_STORAGE_MULTI */
|
|
return STORAGE_FUNCTION(write_sectors)(IF_MD(drive,)start,count,buf);
|
|
#endif /* CONFIG_STORAGE_MULTI */
|
|
}
|
|
|
|
#ifdef CONFIG_STORAGE_MULTI
|
|
|
|
#define DRIVER_MASK 0xff000000
|
|
#define DRIVER_OFFSET 24
|
|
#define DRIVE_MASK 0x00ff0000
|
|
#define DRIVE_OFFSET 16
|
|
#define PARTITION_MASK 0x0000ff00
|
|
|
|
static unsigned int storage_drivers[NUM_DRIVES];
|
|
static unsigned int num_drives;
|
|
|
|
int storage_num_drives(void)
|
|
{
|
|
return num_drives;
|
|
}
|
|
|
|
int storage_driver_type(int drive)
|
|
{
|
|
if ((unsigned int)drive >= num_drives)
|
|
return -1;
|
|
|
|
unsigned int bit = (storage_drivers[drive] & DRIVER_MASK)>>DRIVER_OFFSET;
|
|
return bit ? find_first_set_bit(bit) : -1;
|
|
}
|
|
|
|
void storage_enable(bool on)
|
|
{
|
|
#if (CONFIG_STORAGE & STORAGE_ATA)
|
|
ata_enable(on);
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_MMC)
|
|
mmc_enable(on);
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_SD)
|
|
sd_enable(on);
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_NAND)
|
|
nand_enable(on);
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_RAMDISK)
|
|
ramdisk_enable(on);
|
|
#endif
|
|
}
|
|
|
|
void storage_sleepnow(void)
|
|
{
|
|
#if (CONFIG_STORAGE & STORAGE_ATA)
|
|
ata_sleepnow();
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_MMC)
|
|
mmc_sleepnow();
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_SD)
|
|
//sd_sleepnow();
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_NAND)
|
|
nand_sleepnow();
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_RAMDISK)
|
|
ramdisk_sleepnow();
|
|
#endif
|
|
}
|
|
|
|
bool storage_disk_is_active(void)
|
|
{
|
|
#if (CONFIG_STORAGE & STORAGE_ATA)
|
|
if (ata_disk_is_active()) return true;
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_MMC)
|
|
if (mmc_disk_is_active()) return true;
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_SD)
|
|
//if (sd_disk_is_active()) return true;
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_NAND)
|
|
//if (nand_disk_is_active()) return true;
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_RAMDISK)
|
|
if (ramdisk_disk_is_active()) return true;
|
|
#endif
|
|
|
|
return false;
|
|
}
|
|
|
|
int storage_soft_reset(void)
|
|
{
|
|
int rc=0;
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_ATA)
|
|
if ((rc=ata_soft_reset())) return rc;
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_MMC)
|
|
if ((rc=mmc_soft_reset())) return rc;
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_SD)
|
|
//if ((rc=sd_soft_reset())) return rc;
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_NAND)
|
|
//if ((rc=nand_soft_reset())) return rc;
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_RAMDISK)
|
|
if ((rc=ramdisk_soft_reset())) return rc;
|
|
#endif
|
|
|
|
return rc;
|
|
}
|
|
|
|
#ifdef HAVE_STORAGE_FLUSH
|
|
int storage_flush(void)
|
|
{
|
|
int rc=0;
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_ATA)
|
|
//if ((rc=ata_flush())) return rc;
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_MMC)
|
|
//if ((rc=mmc_flush())) return rc;
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_SD)
|
|
//if ((rc=sd_flush())) return rc;
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_NAND)
|
|
if ((rc=nand_flush())) return rc;
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_RAMDISK)
|
|
//if ((rc=ramdisk_flush())) return rc;
|
|
#endif
|
|
|
|
return rc;
|
|
}
|
|
#endif
|
|
|
|
void storage_spin(void)
|
|
{
|
|
#if (CONFIG_STORAGE & STORAGE_ATA)
|
|
ata_spin();
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_MMC)
|
|
mmc_spin();
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_SD)
|
|
sd_spin();
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_NAND)
|
|
nand_spin();
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_RAMDISK)
|
|
ramdisk_spin();
|
|
#endif
|
|
}
|
|
|
|
void storage_spindown(int seconds)
|
|
{
|
|
#if (CONFIG_STORAGE & STORAGE_ATA)
|
|
ata_spindown(seconds);
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_MMC)
|
|
mmc_spindown(seconds);
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_SD)
|
|
sd_spindown(seconds);
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_NAND)
|
|
nand_spindown(seconds);
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_RAMDISK)
|
|
ramdisk_spindown(seconds);
|
|
#endif
|
|
}
|
|
|
|
#if (CONFIG_LED == LED_REAL)
|
|
void storage_set_led_enabled(bool enabled)
|
|
{
|
|
#if (CONFIG_STORAGE & STORAGE_ATA)
|
|
ata_set_led_enabled(enabled);
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_MMC)
|
|
mmc_set_led_enabled(enabled);
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_SD)
|
|
sd_set_led_enabled(enabled);
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_NAND)
|
|
nand_set_led_enabled(enabled);
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_RAMDISK)
|
|
ramdisk_set_led_enabled(enabled);
|
|
#endif
|
|
}
|
|
#endif /* CONFIG_LED == LED_REAL */
|
|
|
|
long storage_last_disk_activity(void)
|
|
{
|
|
long max=0;
|
|
long t;
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_ATA)
|
|
t=ata_last_disk_activity();
|
|
if (t>max) max=t;
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_MMC)
|
|
t=mmc_last_disk_activity();
|
|
if (t>max) max=t;
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_SD)
|
|
t=sd_last_disk_activity();
|
|
if (t>max) max=t;
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_NAND)
|
|
t=nand_last_disk_activity();
|
|
if (t>max) max=t;
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_RAMDISK)
|
|
t=ramdisk_last_disk_activity();
|
|
if (t>max) max=t;
|
|
#endif
|
|
|
|
return max;
|
|
}
|
|
|
|
int storage_spinup_time(void)
|
|
{
|
|
int max=0;
|
|
int t;
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_ATA)
|
|
t=ata_spinup_time();
|
|
if (t>max) max=t;
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_MMC)
|
|
t=mmc_spinup_time();
|
|
if (t>max) max=t;
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_SD)
|
|
//t=sd_spinup_time();
|
|
//if (t>max) max=t;
|
|
(void)t;
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_NAND)
|
|
t=nand_spinup_time();
|
|
if (t>max) max=t;
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_RAMDISK)
|
|
t=ramdisk_spinup_time();
|
|
if (t>max) max=t;
|
|
#endif
|
|
|
|
return max;
|
|
}
|
|
|
|
#ifdef STORAGE_GET_INFO
|
|
void storage_get_info(int drive, struct storage_info *info)
|
|
{
|
|
int driver=(storage_drivers[drive] & DRIVER_MASK)>>DRIVER_OFFSET;
|
|
int ldrive=(storage_drivers[drive] & DRIVE_MASK)>>DRIVE_OFFSET;
|
|
|
|
switch(driver)
|
|
{
|
|
#if (CONFIG_STORAGE & STORAGE_ATA)
|
|
case STORAGE_ATA:
|
|
return ata_get_info(ldrive,info);
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_MMC)
|
|
case STORAGE_MMC:
|
|
return mmc_get_info(ldrive,info);
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_SD)
|
|
case STORAGE_SD:
|
|
return sd_get_info(ldrive,info);
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_NAND)
|
|
case STORAGE_NAND:
|
|
return nand_get_info(ldrive,info);
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_RAMDISK)
|
|
case STORAGE_RAMDISK:
|
|
return ramdisk_get_info(ldrive,info);
|
|
#endif
|
|
}
|
|
}
|
|
#endif /* STORAGE_GET_INFO */
|
|
|
|
#ifdef HAVE_HOTSWAP
|
|
bool storage_removable(int drive)
|
|
{
|
|
int driver=(storage_drivers[drive] & DRIVER_MASK)>>DRIVER_OFFSET;
|
|
int ldrive=(storage_drivers[drive] & DRIVE_MASK)>>DRIVE_OFFSET;
|
|
|
|
switch(driver)
|
|
{
|
|
#if (CONFIG_STORAGE & STORAGE_ATA)
|
|
case STORAGE_ATA:
|
|
return false;
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_MMC)
|
|
case STORAGE_MMC:
|
|
return mmc_removable(ldrive);
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_SD)
|
|
case STORAGE_SD:
|
|
return sd_removable(ldrive);
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_NAND)
|
|
case STORAGE_NAND:
|
|
return false;
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_RAMDISK)
|
|
case STORAGE_RAMDISK:
|
|
return false;
|
|
#endif
|
|
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool storage_present(int drive)
|
|
{
|
|
int driver=(storage_drivers[drive] & DRIVER_MASK)>>DRIVER_OFFSET;
|
|
int ldrive=(storage_drivers[drive] & DRIVE_MASK)>>DRIVE_OFFSET;
|
|
|
|
switch(driver)
|
|
{
|
|
#if (CONFIG_STORAGE & STORAGE_ATA)
|
|
case STORAGE_ATA:
|
|
return true;
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_MMC)
|
|
case STORAGE_MMC:
|
|
return mmc_present(ldrive);
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_SD)
|
|
case STORAGE_SD:
|
|
return sd_present(ldrive);
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_NAND)
|
|
case STORAGE_NAND:
|
|
return true;
|
|
#endif
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_RAMDISK)
|
|
case STORAGE_RAMDISK:
|
|
return true;
|
|
#endif
|
|
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
#endif /* HAVE_HOTSWAP */
|
|
#endif /*CONFIG_STORAGE_MULTI*/
|