/*************************************************************************** * __________ __ ___. * 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" #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 #ifdef HAVE_IO_PRIORITY /* Same for flash? */ #define STORAGE_MINIMUM_IDLE_TIME (HZ/10) #define STORAGE_DELAY_UNIT (HZ/20) static unsigned int storage_last_thread[NUM_DRIVES]; static unsigned int storage_last_activity[NUM_DRIVES]; static bool storage_should_wait(int drive, int prio) { int other_prio = thread_get_io_priority(storage_last_thread[drive]); if(TIME_BEFORE(current_tick,storage_last_activity[drive]+STORAGE_MINIMUM_IDLE_TIME)) { if(prio<=other_prio) { /* There is another active thread, but we have lower priority */ return false; } else { /* There is another active thread, but it has lower priority */ return true; } } else { /* There's nothing going on anyway */ return false; } } static void storage_wait_turn(IF_MD_NONVOID(int drive)) { #ifndef HAVE_MULTIDRIVE int drive=0; #endif int my_prio = thread_get_io_priority(thread_self()); int loops=my_prio; while(storage_should_wait(drive, my_prio) && (loops--)>=0) { sleep(STORAGE_DELAY_UNIT); } storage_last_thread[drive] = thread_self(); storage_last_activity[drive] = current_tick; } #endif int storage_read_sectors(IF_MD(int drive,) unsigned long start, int count, void* buf) { #ifdef HAVE_IO_PRIORITY storage_wait_turn(IF_MD(drive)); #endif #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 HAVE_IO_PRIORITY storage_wait_turn(IF_MD(drive)); #endif #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; } int storage_init(void) { int rc=0; 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; imax) 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; #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 #endif /*CONFIG_STORAGE_MULTI*/