1
0
Fork 0
forked from len0rd/rockbox
foxbox/firmware/export/storage.h
Michael Sevakis 1654efc313 Unify storage threads into one
* Editing a bunch of drivers' thread routines in order to
implement a new feature is tedious.

* No matter the number of storage drivers, they share one thread.
No extra threads needed for CONFIG_STORAGE_MULTI.

* Each has an event callback called by the storage thread.

* A default callback is provided to fake sleeping in order to
trigger idle callbacks. It could also do other default processing.
Changes to it will be part of driver code without editing each
one.

* Drivers may sleep and wake as they please as long as they give
a low pulse on their storage bit to ask to go into sleep mode.
Idle callback is called on its behalf and driver immediately put
into sleep mode.

* Drivers may indicate they are to continue receiving events in
USB mode, otherwise they receve nothing until disconnect (they
do receive SYS_USB_DISCONNECTED no matter what).

* Rework a few things to keep the callback implementation sane
and maintainable. ata.c was dreadful with all those bools; make
it a state machine and easier to follow. Remove last_user_activity;
it has no purpose that isn't served by keeping the disk active
through last_disk_activity instead.

* Even-out stack sizes partly because of a lack of a decent place
to define them by driver or SoC or whatever; it doesn't seem too
critical to do that anyway. Many are simply too large while at
least one isn't really adequate. They may be individually
overridden if necessary (figure out where). The thread uses the
greatest size demanded. Newer file code is much more frugal with
stack space. I barely see use crack 50% after idle callbacks
(usually mid-40s). Card insert/eject doesn't demand much.

* No forcing of idle callbacks. If it isn't necessary for one or
more non-disk storage types, it really isn't any more necessary for
disk storage. Besides, it makes the whole thing easier to implement.

Change-Id: Id30c284d82a8af66e47f2cfe104c52cbd8aa7215
2017-10-26 14:35:41 -04:00

311 lines
11 KiB
C

/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2002 by Alan Korr
* 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.
*
****************************************************************************/
#ifndef __STORAGE_H__
#define __STORAGE_H__
#include <stdbool.h>
#include "config.h" /* for HAVE_MULTIDRIVE or not */
#include "mv.h"
#include <kernel.h>
#if (CONFIG_STORAGE & STORAGE_HOSTFS) || defined(SIMULATOR)
#define HAVE_HOSTFS
#endif
#if (CONFIG_STORAGE & STORAGE_SD)
#include "sd.h"
#endif
#if (CONFIG_STORAGE & STORAGE_MMC)
#include "mmc.h"
#endif
#if (CONFIG_STORAGE & STORAGE_ATA)
#include "ata.h"
#endif
#if (CONFIG_STORAGE & STORAGE_NAND)
#include "nand.h"
#endif
#if (CONFIG_STORAGE & STORAGE_RAMDISK)
#include "ramdisk.h"
#endif
enum
{
Q_STORAGE_TICK = 1,
Q_STORAGE_SLEEP,
Q_STORAGE_SLEEPNOW,
#ifdef STORAGE_CLOSE
Q_STORAGE_CLOSE,
#endif
};
#define STG_EVENT_ASSERT_ACTIVE(type) \
({ intptr_t __data = (data); \
*((unsigned int *)(__data)) |= (type); })
static FORCE_INLINE int storage_event_default_handler(long id,
intptr_t data,
long last_activity,
unsigned int type)
{
/* fake sleep in order to trigger storage idle sequence */
static long slept_at = -1;
if (id == Q_STORAGE_TICK) {
if (last_activity == slept_at ||
TIME_BEFORE(current_tick, last_activity + 3*HZ)) {
STG_EVENT_ASSERT_ACTIVE(type);
}
}
else if (id == Q_STORAGE_SLEEPNOW) {
slept_at = last_activity;
}
return 0;
}
#if (CONFIG_STORAGE & STORAGE_SD)
int sd_event(long id, intptr_t data);
#endif
#if (CONFIG_STORAGE & STORAGE_MMC)
int mmc_event(long id, intptr_t data);
#endif
#if (CONFIG_STORAGE & STORAGE_ATA)
int ata_event(long id, intptr_t data);
#endif
#if (CONFIG_STORAGE & STORAGE_NAND)
int nand_event(long id, intptr_t data);
#endif
#if (CONFIG_STORAGE & STORAGE_RAMDISK)
int ramdisk_event(long id, intptr_t data);
#endif
struct storage_info
{
unsigned int sector_size;
unsigned int num_sectors;
char *vendor;
char *product;
char *revision;
};
int storage_init(void) STORAGE_INIT_ATTR;
void storage_close(void);
#ifdef HAVE_HOSTFS
#include "hostfs.h"
/* stubs for the plugin api */
static inline void stub_storage_sleep(void) {}
static inline void stub_storage_spin(void) {}
static inline void stub_storage_spindown(int timeout) { (void)timeout; }
static inline int stub_storage_event(long id, intptr_t data)
{ return 0; (void)id; (void)data; }
#else /* ndef HAVE_HOSTFS */
#if (CONFIG_STORAGE & STORAGE_ATA)
void storage_sleep(void);
#else
static inline void storage_sleep(void) {}
#endif
#endif /* HAVE_HOSTFS */
#if !defined(CONFIG_STORAGE_MULTI) || defined(HAVE_HOSTFS)
/* storage_spindown, storage_sleep and storage_spin are passed as
* pointers, which doesn't work with argument-macros.
*/
#define storage_num_drives() NUM_DRIVES
#if defined(HAVE_HOSTFS)
#define STORAGE_FUNCTION(NAME) (stub_## NAME)
#define storage_event stub_storage_event
#define storage_spindown stub_storage_spindown
#define storage_sleep stub_storage_sleep
#define storage_spin stub_storage_spin
#define storage_enable(on)
#define storage_sleepnow()
#define storage_disk_is_active() 0
#define storage_soft_reset()
#define storage_init() hostfs_init()
#ifdef HAVE_STORAGE_FLUSH
#define storage_flush() hostfs_flush()
#endif
#define storage_last_disk_activity() (-1)
#define storage_spinup_time() 0
#define storage_get_identify() (NULL) /* not actually called anywher */
#ifdef STORAGE_GET_INFO
#error storage_get_info not implemented
#endif
#ifdef HAVE_HOTSWAP
#define storage_removable(drive) hostfs_removable(IF_MD(drive))
#define storage_present(drive) hostfs_present(IF_MD(drive))
#endif
#define storage_driver_type(drive) hostfs_driver_type(IF_MV(drive))
#elif (CONFIG_STORAGE & STORAGE_ATA)
#define STORAGE_FUNCTION(NAME) (ata_## NAME)
#define storage_spindown ata_spindown
#define storage_spin ata_spin
#define storage_enable(on) ata_enable(on)
#define storage_sleepnow() ata_sleepnow()
#define storage_disk_is_active() ata_disk_is_active()
#define storage_soft_reset() ata_soft_reset()
#ifdef HAVE_STORAGE_FLUSH
#define storage_flush() (void)0
#endif
#define storage_last_disk_activity() ata_last_disk_activity()
#define storage_spinup_time() ata_spinup_time()
#define storage_get_identify() ata_get_identify()
#ifdef STORAGE_GET_INFO
#define storage_get_info(drive, info) ata_get_info(IF_MD(drive,) info)
#endif
#ifdef HAVE_HOTSWAP
#define storage_removable(drive) ata_removable(IF_MD(drive))
#define storage_present(drive) ata_present(IF_MD(drive))
#endif
#define storage_driver_type(drive) (STORAGE_ATA_NUM)
#elif (CONFIG_STORAGE & STORAGE_SD)
#define STORAGE_FUNCTION(NAME) (sd_## NAME)
#define storage_spindown sd_spindown
#define storage_spin sd_spin
#define storage_enable(on) sd_enable(on)
#define storage_sleepnow() sd_sleepnow()
#define storage_disk_is_active() 0
#define storage_soft_reset() (void)0
#ifdef HAVE_STORAGE_FLUSH
#define storage_flush() (void)0
#endif
#define storage_last_disk_activity() sd_last_disk_activity()
#define storage_spinup_time() 0
#define storage_get_identify() sd_get_identify()
#ifdef STORAGE_GET_INFO
#define storage_get_info(drive, info) sd_get_info(IF_MD(drive,) info)
#endif
#ifdef HAVE_HOTSWAP
#define storage_removable(drive) sd_removable(IF_MD(drive))
#define storage_present(drive) sd_present(IF_MD(drive))
#endif
#define storage_driver_type(drive) (STORAGE_SD_NUM)
#elif (CONFIG_STORAGE & STORAGE_MMC)
#define STORAGE_FUNCTION(NAME) (mmc_## NAME)
#define storage_spindown mmc_spindown
#define storage_spin mmc_spin
#define storage_enable(on) mmc_enable(on)
#define storage_sleepnow() mmc_sleepnow()
#define storage_disk_is_active() mmc_disk_is_active()
#define storage_soft_reset() (void)0
#ifdef HAVE_STORAGE_FLUSH
#define storage_flush() (void)0
#endif
#define storage_last_disk_activity() mmc_last_disk_activity()
#define storage_spinup_time() 0
#define storage_get_identify() mmc_get_identify()
#ifdef STORAGE_GET_INFO
#define storage_get_info(drive, info) mmc_get_info(IF_MD(drive,) info)
#endif
#ifdef HAVE_HOTSWAP
#define storage_removable(drive) mmc_removable(IF_MD(drive))
#define storage_present(drive) mmc_present(IF_MD(drive))
#endif
#define storage_driver_type(drive) (STORAGE_MMC_NUM)
#elif (CONFIG_STORAGE & STORAGE_NAND)
#define STORAGE_FUNCTION(NAME) (nand_## NAME)
#define storage_spindown nand_spindown
#define storage_spin nand_spin
#define storage_enable(on) (void)0
#define storage_sleepnow() nand_sleepnow()
#define storage_disk_is_active() 0
#define storage_soft_reset() (void)0
#ifdef HAVE_STORAGE_FLUSH
#define storage_flush() nand_flush()
#endif
#define storage_last_disk_activity() nand_last_disk_activity()
#define storage_spinup_time() 0
#define storage_get_identify() nand_get_identify()
#ifdef STORAGE_GET_INFO
#define storage_get_info(drive, info) nand_get_info(IF_MD(drive,) info)
#endif
#ifdef HAVE_HOTSWAP
#define storage_removable(drive) nand_removable(IF_MD(drive))
#define storage_present(drive) nand_present(IF_MD(drive))
#endif
#define storage_driver_type(drive) (STORAGE_NAND_NUM)
#elif (CONFIG_STORAGE & STORAGE_RAMDISK)
#define STORAGE_FUNCTION(NAME) (ramdisk_## NAME)
#define storage_spindown ramdisk_spindown
#define storage_spin ramdisk_spin
#define storage_enable(on) (void)0
#define storage_sleepnow() ramdisk_sleepnow()
#define storage_disk_is_active() 0
#define storage_soft_reset() (void)0
#ifdef HAVE_STORAGE_FLUSH
#define storage_flush() (void)0
#endif
#define storage_last_disk_activity() ramdisk_last_disk_activity()
#define storage_spinup_time() 0
#define storage_get_identify() ramdisk_get_identify()
#ifdef STORAGE_GET_INFO
#define storage_get_info(drive, info) ramdisk_get_info(IF_MD(drive,) info)
#endif
#ifdef HAVE_HOTSWAP
#define storage_removable(drive) ramdisk_removable(IF_MD(drive))
#define storage_present(drive) ramdisk_present(IF_MD(drive))
#endif
#define storage_driver_type(drive) (STORAGE_RAMDISK_NUM)
#else
//#error No storage driver!
#endif
#else /* CONFIG_STORAGE_MULTI || !HAVE_HOSTFS */
/* Multi-driver use normal functions */
void storage_enable(bool on);
void storage_sleepnow(void);
bool storage_disk_is_active(void);
int storage_soft_reset(void);
int storage_flush(void);
void storage_spin(void);
void storage_spindown(int seconds);
long storage_last_disk_activity(void);
int storage_spinup_time(void);
int storage_num_drives(void);
#ifdef STORAGE_GET_INFO
void storage_get_info(int drive, struct storage_info *info);
#endif
#ifdef HAVE_HOTSWAP
bool storage_removable(int drive);
bool storage_present(int drive);
#endif
int storage_driver_type(int drive);
#endif /* NOT CONFIG_STORAGE_MULTI and NOT SIMULATOR*/
int storage_read_sectors(IF_MD(int drive,) unsigned long start, int count, void* buf);
int storage_write_sectors(IF_MD(int drive,) unsigned long start, int count, const void* buf);
#endif