200 lines
7.5 KiB
C
200 lines
7.5 KiB
C
/*
|
|
* c't-Bot
|
|
*
|
|
* 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 program is distributed in the hope that it will be
|
|
* useful, but WITHOUT ANY WARRANTY; without even the implied
|
|
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
* PURPOSE. See the GNU General Public License for more details.
|
|
* You should have received a copy of the GNU General Public
|
|
* License along with this program; if not, write to the Free
|
|
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
|
* MA 02111-1307, USA.
|
|
*
|
|
*/
|
|
|
|
/*!
|
|
* @file mmc-emu_pc.c
|
|
* @brief MMC / SD-Card Emulation fuer PC
|
|
* @author Timo Sandmann (mail@timosandmann.de)
|
|
* @date 10.12.2006
|
|
*/
|
|
|
|
/* Die PC-Emulation einer MMC / SD-Card ermoeglicht es, am PC dieselben Funktionen zu benutzen, wie bei einer echten
|
|
* MMC / SD-Card. Als Speichermedium dient hier eine Datei (MMC_EMU_FILE), deren Groesse sich mit MMC_EMU_SIZE in Byte
|
|
* einstellen laesst. Ist die Datei nicht vorhanden oder derzeit kleiner als MMC_EMU_SIZE, wird sie angelegt bzw.
|
|
* vergroessert. Achtung, startet man den C-Bot vom Sim aus, liegt die Datei, falls kein absoluter Pfad angegeben wurde, im
|
|
* Verzeichnis dem ct-Sims, von der Konsole aus gestartet erwartet / erzeugt der Code die Datei im Unterverzeichnis
|
|
* "Debug-Linux" bzw. "Debug-W32".
|
|
* Eine sinnvolle (und die derzeit einzig moegliche) Verwendung der Emulation ergibt sich im Zusammenspiel mit dem
|
|
* Virtual Memory Management fuer MMC. Ein Verhalten kann in diesem Fall immer auf dieselbe Art und Weise Speicher anfordern,
|
|
* je nach System liegt dieser physisch dann entweder auf einer MMC / SD-Card (MCU) oder in einer Datei (PC). Fuer das
|
|
* Verhalten ergibt sich kein Unterschied und es kann einfach derselbe Code verwendet werden.
|
|
* Moechte man die Funktion mmc_fopen() benutzen, also auf FAT16-Dateien zugreifen, so ist zu beachten, dass deren "Dateiname"
|
|
* in der Datei fuer die Emulation am Anfang eines 512 Byte grossen Blocks steht (denn auf einer echten MMC / SD-Card ezeugt
|
|
* ein Betriebssystem eine neue Datei immer am Anfang eines Clusters und mmc_fopen() sucht nur dort nach dem "Dateinamen").
|
|
* Im Moment gibt es noch keine Funktion zum Anlegen einer neuen Datei auf einer echten oder emulierten MMC / SD-Card.
|
|
* Die Code der Emulation ist voellig symmetrisch zum Code fuer eine echte MMC / SD-Card aufgebaut.
|
|
*/
|
|
|
|
#include "ct-Bot.h"
|
|
#include <stdio.h>
|
|
#include "mmc-emu.h"
|
|
#include "mmc-vm.h"
|
|
#include "display.h"
|
|
|
|
#ifdef PC
|
|
#ifdef MMC_VM_AVAILABLE
|
|
|
|
#define MMC_EMU_SIZE 0x2000000 /*!< Groesse der emulierten Karte in Byte */
|
|
#define MMC_EMU_FILE "mmc_emu.dat" /*!< Name / Pfad der Datei fuer die Emulation */
|
|
|
|
volatile uint8 mmc_emu_init_state=1; /*!< Initialierungsstatus der Karte, 0: ok, 1: Fehler */
|
|
static FILE* mmc_emu_file; /*!< Der Inhalt der emulierten Karte wird einfach in eine Datei geschrieben */
|
|
|
|
/*!
|
|
* Checkt Initialisierung der emulierten Karte
|
|
* @return 0, wenn initialisiert
|
|
* @see mcu/mmc.c
|
|
* @date 29.12.2006
|
|
*/
|
|
inline uint8 mmc_emu_get_init_state(void){
|
|
return mmc_emu_init_state;
|
|
}
|
|
|
|
/*!
|
|
* Initialisiere die emulierte SD/MMC-Karte
|
|
* @return 0 wenn allles ok, sonst 1
|
|
* @see mcu/mmc.c
|
|
* @date 29.12.2006
|
|
*/
|
|
uint8 mmc_emu_init(void){
|
|
mmc_emu_init_state = 0;
|
|
mmc_emu_file = fopen(MMC_EMU_FILE, "r+"); // Datei versuchen zu oeffnen
|
|
if (mmc_emu_file == NULL){
|
|
/* Datei existiert noch nicht oder kann nicht erzeugt werden */
|
|
mmc_emu_file = fopen(MMC_EMU_FILE, "w+"); // Datei neu anlegen
|
|
if (mmc_emu_file == NULL) {
|
|
/* Datei kann nicht erzeugt werden */
|
|
mmc_emu_init_state = 1;
|
|
return 1;
|
|
}
|
|
}
|
|
if (mmc_emu_get_size() < MMC_EMU_SIZE){
|
|
/* vorhandene Datei ist zu klein, also auf MMC_EMU_SIZE vergroessern */
|
|
mmc_emu_init_state = 1;
|
|
if (fseek(mmc_emu_file, MMC_EMU_SIZE-1, SEEK_SET) != 0) return 2;
|
|
if (putc(0, mmc_emu_file) != 0) return 3;
|
|
if (fflush(mmc_emu_file) != 0) return 4;
|
|
mmc_emu_init_state = 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*!
|
|
* Liest einen Block von der emulierten Karte
|
|
* @param addr Nummer des 512-Byte Blocks
|
|
* @param buffer Puffer von mindestens 512 Byte
|
|
* @return 0 wenn alles ok ist
|
|
* @see mcu/mmc.c
|
|
* @date 10.12.2006
|
|
*/
|
|
uint8 mmc_emu_read_sector(uint32 addr, uint8* buffer){
|
|
if (mmc_emu_get_init_state() != 0 && mmc_emu_init() !=0) return 1;
|
|
if (fseek(mmc_emu_file, addr<<9, SEEK_SET) != 0) return 2; // Adresse in Byte umrechnen und an Dateiposition springen
|
|
if (fread(buffer, 512, 1, mmc_emu_file) != 1) return 3; // Block lesen
|
|
return 0;
|
|
}
|
|
|
|
/*!
|
|
* Schreibt einen 512-Byte Sektor auf die emulierte Karte
|
|
* @param addr Nummer des 512-Byte Blocks
|
|
* @param buffer Zeiger auf den Puffer
|
|
* @param async Wird bei der PC-Version nicht ausgewertet
|
|
* @return 0 wenn alles ok ist
|
|
* @date 10.12.2006
|
|
* @see mcu/mmc.c
|
|
*/
|
|
uint8 mmc_emu_write_sector(uint32 addr, uint8* buffer, uint8 async){
|
|
if (mmc_emu_get_init_state() != 0 && mmc_emu_init() !=0) return 1;
|
|
if (fseek(mmc_emu_file, addr<<9, SEEK_SET) != 0) return 2; // Adresse in Byte umrechnen und an Dateiposition springen
|
|
if (fwrite(buffer, 512, 1, mmc_emu_file) != 1) return 3; // Block schreiben
|
|
if (fflush(mmc_emu_file) != 0) return 4; // Puffer leeren
|
|
return 0;
|
|
}
|
|
|
|
/*!
|
|
* Liefert die Groesse der Karte zurueck
|
|
* @return Groesse der emulierten Karte in Byte.
|
|
* @date 29.12.2006
|
|
*/
|
|
uint32 mmc_emu_get_size(void){
|
|
if (mmc_emu_get_init_state() != 0 && mmc_emu_init() !=0) return 0;
|
|
if (fseek(mmc_emu_file, 0L, SEEK_END) != 0) return 0; // Groesse der emulierten Karte = Groesse der Datei
|
|
return ftell(mmc_emu_file)+1;
|
|
}
|
|
|
|
/*!
|
|
* Testet VM und MMC / SD-Card Emulation am PC
|
|
* @date 30.12.2006
|
|
*/
|
|
uint8 mmc_emu_test(void){
|
|
/* Initialisierung checken */
|
|
if (mmc_emu_init_state != 0 && mmc_emu_init() != 0) return 1;
|
|
uint16 i;
|
|
static uint16 pagefaults = 0;
|
|
/* virtuelle Adressen holen */
|
|
static uint32 v_addr1 = 0;
|
|
static uint32 v_addr2 = 0;
|
|
static uint32 v_addr3 = 0;
|
|
static uint32 v_addr4 = 0;
|
|
if (v_addr1 == 0) v_addr1 = mmcalloc(512, 1); // Testdaten 1
|
|
if (v_addr2 == 0) v_addr2 = mmcalloc(512, 1); // Testdaten 2
|
|
if (v_addr3 == 0) v_addr3 = mmcalloc(512, 1); // Dummy 1
|
|
if (v_addr4 == 0) v_addr4 = mmcalloc(512, 1); // Dummy 2
|
|
/* Pointer auf Puffer holen */
|
|
uint8* p_addr = mmc_get_data(v_addr1);
|
|
if (p_addr == NULL) return 2;
|
|
/* Testdaten schreiben */
|
|
for (i=0; i<512; i++)
|
|
p_addr[i] = (i & 0xff);
|
|
/* Pointer auf zweiten Speicherbereich holen */
|
|
p_addr = mmc_get_data(v_addr3);
|
|
if (p_addr == NULL) return 3;
|
|
/* Testdaten Teil 2 schreiben */
|
|
for (i=0; i<512; i++)
|
|
p_addr[i] = 255 - (i & 0xff);
|
|
/* kleiner LRU-Test */
|
|
p_addr = mmc_get_data(v_addr1);
|
|
p_addr = mmc_get_data(v_addr4);
|
|
p_addr = mmc_get_data(v_addr1);
|
|
p_addr = mmc_get_data(v_addr3);
|
|
p_addr = mmc_get_data(v_addr1);
|
|
p_addr = mmc_get_data(v_addr4);
|
|
/* Pointer auf Testdaten Teil 1 holen */
|
|
p_addr = mmc_get_data(v_addr1);
|
|
if (p_addr == NULL) return 4;
|
|
/* Testdaten 1 vergleichen */
|
|
for (i=0; i<512; i++)
|
|
if (p_addr[i] != (i & 0xff)) return 5;
|
|
/* Pointer auf Testdaten Teil 2 holen */
|
|
p_addr = mmc_get_data(v_addr3);
|
|
if (p_addr == NULL) return 6;
|
|
/* Testdaten 2 vergleichen */
|
|
for (i=0; i<512; i++)
|
|
if (p_addr[i] != (255 - (i & 0xff))) return 7;
|
|
/* Pagefaults merken */
|
|
pagefaults = mmc_get_pagefaults();
|
|
/* kleine Statistik ausgeben */
|
|
display_cursor(3,1);
|
|
display_printf("Pagefaults: %5u ", pagefaults);
|
|
// hierher kommen wir nur, wenn alles ok ist
|
|
return 0;
|
|
}
|
|
|
|
#endif // MMC_VM_AVAILABLE
|
|
#endif // PC
|