diff --git a/P8000_WDC_Emulator/P8000_WDC_Emulator/Debug/Makefile b/P8000_WDC_Emulator/P8000_WDC_Emulator/Debug/Makefile
index 95ad55b..bace23e 100755
--- a/P8000_WDC_Emulator/P8000_WDC_Emulator/Debug/Makefile
+++ b/P8000_WDC_Emulator/P8000_WDC_Emulator/Debug/Makefile
@@ -36,6 +36,7 @@ SUBDIRS :=
# Add inputs and outputs from these tool invocations to the build variables
C_SRCS += \
../main.c \
+../mmc.c \
../uart.c \
../wdc_if_pio.c \
../wdc_if_sdcard.c \
@@ -50,6 +51,7 @@ ASM_SRCS +=
OBJS += \
main.o \
+mmc.o \
uart.o \
wdc_if_pio.o \
wdc_if_sdcard.o \
@@ -58,6 +60,7 @@ wdc_ram.o
OBJS_AS_ARGS += \
main.o \
+mmc.o \
uart.o \
wdc_if_pio.o \
wdc_if_sdcard.o \
@@ -66,6 +69,7 @@ wdc_ram.o
C_DEPS += \
main.d \
+mmc.d \
uart.d \
wdc_if_pio.d \
wdc_if_sdcard.d \
@@ -74,6 +78,7 @@ wdc_ram.d
C_DEPS_AS_ARGS += \
main.d \
+mmc.d \
uart.d \
wdc_if_pio.d \
wdc_if_sdcard.d \
@@ -100,10 +105,12 @@ OUTPUT_FILE_DEP:= ./makedep.mk
+
+
./%.o: .././%.c
@echo Building file: $<
@echo Invoking: AVR/GNU C Compiler : (AVR_8_bit_GNU_Toolchain_3.4.0_663) 4.6.2
- $(QUOTE)C:\Program Files (x86)\Atmel\Atmel Studio 6.0\extensions\Atmel\AVRGCC\3.4.0.65\AVRToolchain\bin\avr-gcc.exe$(QUOTE) -funsigned-char -funsigned-bitfields -O1 -fpack-struct -fshort-enums -g2 -Wall -Wundef -Werror -pedantic -pedantic-errors -c -std=gnu99 -save-temps -MD -MP -MF "$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -MT"$(@:%.o=%.o)" -mmcu=atmega1284p -o"$@" "$<"
+ $(QUOTE)C:\Program Files (x86)\Atmel\Atmel Studio 6.0\extensions\Atmel\AVRGCC\3.4.0.65\AVRToolchain\bin\avr-gcc.exe$(QUOTE) -funsigned-char -funsigned-bitfields -O1 -fpack-struct -fshort-enums -g2 -Wall -Wundef -Werror -pedantic -pedantic-errors -c -std=gnu99 -MD -MP -MF "$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -MT"$(@:%.o=%.o)" -mmcu=atmega1284p -o"$@" "$<"
@echo Finished building: $<
diff --git a/P8000_WDC_Emulator/P8000_WDC_Emulator/Debug/makedep.mk b/P8000_WDC_Emulator/P8000_WDC_Emulator/Debug/makedep.mk
index 84642ee..78fdc23 100755
--- a/P8000_WDC_Emulator/P8000_WDC_Emulator/Debug/makedep.mk
+++ b/P8000_WDC_Emulator/P8000_WDC_Emulator/Debug/makedep.mk
@@ -4,6 +4,8 @@
main.c
+mmc.c
+
uart.c
wdc_if_pio.c
diff --git a/P8000_WDC_Emulator/P8000_WDC_Emulator/P8000_WDC_Emulator.cproj b/P8000_WDC_Emulator/P8000_WDC_Emulator/P8000_WDC_Emulator.cproj
index a24869c..b0e7335 100644
--- a/P8000_WDC_Emulator/P8000_WDC_Emulator/P8000_WDC_Emulator.cproj
+++ b/P8000_WDC_Emulator/P8000_WDC_Emulator/P8000_WDC_Emulator.cproj
@@ -45,28 +45,27 @@
- True
- True
- True
- True
- True
- Optimize (-O1)
- True
- True
- Default (-g2)
- True
- True
- True
- True
- True
- True
-
-
- m
-
-
- Default (-Wa,-g)
-
+ True
+ True
+ True
+ True
+ True
+ Optimize (-O1)
+ True
+ True
+ Default (-g2)
+ True
+ True
+ True
+ True
+ True
+
+
+ m
+
+
+ Default (-Wa,-g)
+
@@ -79,6 +78,12 @@
compile
+
+ compile
+
+
+ compile
+
compile
diff --git a/P8000_WDC_Emulator/P8000_WDC_Emulator/wdc_drv_mmc.c b/P8000_WDC_Emulator/P8000_WDC_Emulator/wdc_drv_mmc.c
new file mode 100644
index 0000000..7c64c04
--- /dev/null
+++ b/P8000_WDC_Emulator/P8000_WDC_Emulator/wdc_drv_mmc.c
@@ -0,0 +1,302 @@
+/*#######################################################################################
+Connect AVR to MMC/SD
+
+Copyright (C) 2004 Ulrich Radig
+
+Bei Fragen und Verbesserungen wendet euch per EMail an
+
+mail@ulrichradig.de
+
+oder im Forum meiner Web Page : www.ulrichradig.de
+
+Dieses Programm ist freie Software. Sie können es unter den Bedingungen der
+GNU General Public License, wie von der Free Software Foundation veröffentlicht,
+weitergeben und/oder modifizieren, entweder gemäß Version 2 der Lizenz oder
+(nach Ihrer Option) jeder späteren Version.
+
+Die Veröffentlichung dieses Programms erfolgt in der Hoffnung,
+daß es Ihnen von Nutzen sein wird, aber OHNE IRGENDEINE GARANTIE,
+sogar ohne die implizite Garantie der MARKTREIFE oder der VERWENDBARKEIT
+FÜR EINEN BESTIMMTEN ZWECK. Details finden Sie in der GNU General Public License.
+
+Sie sollten eine Kopie der GNU General Public License zusammen mit diesem
+Programm erhalten haben.
+Falls nicht, schreiben Sie an die Free Software Foundation,
+Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+#######################################################################################*/
+
+#include "mmc.h"
+
+//############################################################################
+//Routine zur Initialisierung der MMC/SD-Karte (SPI-MODE)
+uint8_t mmc_init ()
+//############################################################################
+{
+ uint8_t Timeout = 0;
+
+ //Konfiguration des Ports an der die MMC/SD-Karte angeschlossen wurde
+ MMC_Direction_REG &= ~ ( 1 << SPI_DI ); //Setzen von Pin MMC_DI auf Input
+ MMC_Direction_REG |= ( 1 << SPI_Clock ); //Setzen von Pin MMC_Clock auf Output
+ MMC_Direction_REG |= ( 1 << SPI_DO ); //Setzen von Pin MMC_DO auf Output
+ MMC_Direction_REG |= ( 1 << MMC_Chip_Select ); //Setzen von Pin MMC_Chip_Select auf Output
+ MMC_Write |= ( 1 << MMC_Chip_Select ); //Setzt den Pin MMC_Chip_Select auf High Pegel
+
+ for ( uint8_t a = 0; a < 200; a++ ) {
+ nop();
+ }; //Wartet eine kurze Zeit
+
+#if SPI_Mode
+ //Aktiviren des SPI - Bus, Clock = Idel LOW
+ //SPI Clock teilen durch 128
+ SPCR = ( 1 << SPE ) | ( 1 << MSTR ) | ( 1 << SPR0 ) | ( 1 << SPR1 ); //Enable SPI, SPI in Master Mode
+ SPSR = ( 0 << SPI2X );
+#endif
+
+ //Initialisiere MMC/SD-Karte in den SPI-Mode
+ for ( uint8_t b = 0; b < 0x0f; b++ ) { //Sendet min 74+ Clocks an die MMC/SD-Karte
+ mmc_write_byte ( 0xff );
+ }
+
+ //Sendet Commando CMD0 an MMC/SD-Karte
+ uint8_t CMD[] = {0x40, 0x00, 0x00, 0x00, 0x00, 0x95};
+ while ( mmc_write_command ( CMD ) != 1 ) {
+ if ( Timeout++ > 200 ) {
+ MMC_Disable();
+ return ( 1 ); //Abbruch bei Commando1 (Return Code1)
+ }
+ }
+ //Sendet Commando CMD1 an MMC/SD-Karte
+ Timeout = 0;
+ CMD[0] = 0x41;//Commando 1
+ CMD[5] = 0xFF;
+ while ( mmc_write_command ( CMD ) != 0 ) {
+ if ( Timeout++ > 400 ) {
+ MMC_Disable();
+ return ( 2 ); //Abbruch bei Commando2 (Return Code2)
+ }
+ }
+#if SPI_Mode
+ //SPI Bus auf max Geschwindigkeit
+ SPCR &= ~ ( ( 1 << SPR0 ) | ( 1 << SPR1 ) );
+ SPSR = SPSR | ( 1 << SPI2X );
+#endif
+
+ //set MMC_Chip_Select to high (MMC/SD-Karte Inaktiv)
+ MMC_Disable();
+ return ( 0 );
+}
+
+//############################################################################
+//Sendet ein Commando an die MMC/SD-Karte
+uint8_t mmc_write_command ( uint8_t *cmd )
+//############################################################################
+{
+ uint8_t tmp = 0xff;
+ uint8_t Timeout = 0;
+
+ //set MMC_Chip_Select to high (MMC/SD-Karte Inaktiv)
+ MMC_Disable();
+
+ //sendet 8 Clock Impulse
+ mmc_write_byte ( 0xFF );
+
+ //set MMC_Chip_Select to low (MMC/SD-Karte Aktiv)
+ MMC_Enable();
+
+ //sendet 6 Byte Commando
+ for ( uint8_t a = 0; a < 0x06; a++ ) { //sendet 6 Byte Commando zur MMC/SD-Karte
+ mmc_write_byte ( *cmd++ );
+ }
+
+ //Wartet auf ein gültige Antwort von der MMC/SD-Karte
+ while ( tmp == 0xff ) {
+ tmp = mmc_read_byte();
+ if ( Timeout++ > 500 ) {
+ break; //Abbruch da die MMC/SD-Karte nicht Antwortet
+ }
+ }
+ return ( tmp );
+}
+
+//############################################################################
+//Routine zum Empfangen eines Bytes von der MMC-Karte
+uint8_t mmc_read_byte ( void )
+//############################################################################
+{
+ uint8_t Byte = 0;
+#if SPI_Mode //Routine für Hardware SPI
+ SPDR = 0xff;
+ while ( ! ( SPSR & ( 1 << SPIF ) ) ) {};
+ Byte = SPDR;
+
+#else //Routine für Software SPI
+ for ( uint8_t a = 8; a > 0; a-- ) { //das Byte wird Bitweise nacheinander Empangen MSB First
+ MMC_Write &= ~ ( 1 << SPI_Clock ); //erzeugt ein Clock Impuls (Low)
+
+ if ( bit_is_set ( MMC_Read, SPI_DI ) > 0 ) { //Lesen des Pegels von MMC_DI
+ Byte |= ( 1 << ( a - 1 ) );
+ } else {
+ Byte &= ~ ( 1 << ( a - 1 ) );
+ }
+ MMC_Write |= ( 1 << SPI_Clock ); //setzt Clock Impuls wieder auf (High)
+ }
+#endif
+ return ( Byte );
+}
+
+
+//############################################################################
+//Routine zum Senden eines Bytes zur MMC-Karte
+void mmc_write_byte ( uint8_t Byte )
+//############################################################################
+{
+#if SPI_Mode //Routine für Hardware SPI
+
+ SPDR = Byte; //Sendet ein Byte
+
+ while ( ! ( SPSR & ( 1 << SPIF ) ) ) { //Wartet bis Byte gesendet wurde
+ }
+
+#else //Routine für Software SPI
+ for ( uint8_t a = 8; a > 0; a-- ) { //das Byte wird Bitweise nacheinander Gesendet MSB First
+ if ( bit_is_set ( Byte, ( a - 1 ) ) > 0 ) { //Ist Bit a in Byte gesetzt
+ MMC_Write |= ( 1 << SPI_DO ); //Set Output High
+ } else {
+ MMC_Write &= ~ ( 1 << SPI_DO ); //Set Output Low
+ }
+ MMC_Write &= ~ ( 1 << SPI_Clock ); //erzeugt ein Clock Impuls (LOW)
+
+ MMC_Write |= ( 1 << SPI_Clock ); //setzt Clock Impuls wieder auf (High)
+ }
+ MMC_Write |= ( 1 << SPI_DO ); //setzt Output wieder auf High
+#endif
+}
+
+//############################################################################
+//Routine zum schreiben eines Blocks(512Byte) auf die MMC/SD-Karte
+uint8_t mmc_write_sector ( uint32_t addr, uint8_t *Buffer )
+//############################################################################
+{
+ uint8_t tmp;
+ //Commando 24 zum schreiben eines Blocks auf die MMC/SD - Karte
+ uint8_t cmd[] = {0x58, 0x00, 0x00, 0x00, 0x00, 0xFF};
+
+ /*Die Adressierung der MMC/SD-Karte wird in Bytes angegeben,
+ addr wird von Blocks zu Bytes umgerechnet danach werden
+ diese in das Commando eingefügt*/
+ addr = addr << 9; //addr = addr * 512
+
+ cmd[1] = ( ( addr & 0xFF000000 ) >> 24 );
+ cmd[2] = ( ( addr & 0x00FF0000 ) >> 16 );
+ cmd[3] = ( ( addr & 0x0000FF00 ) >> 8 );
+
+ //Sendet Commando cmd24 an MMC/SD-Karte (Write 1 Block/512 Bytes)
+ tmp = mmc_write_command ( cmd );
+ if ( tmp != 0 ) {
+ return ( tmp );
+ }
+
+ //Wartet einen Moment und sendet einen Clock an die MMC/SD-Karte
+ for ( uint16_t a = 0; a < 100; a++ ) {
+ mmc_read_byte();
+ }
+
+ //Sendet Start Byte an MMC/SD-Karte
+ mmc_write_byte ( 0xFE );
+
+ //Schreiben des Bolcks (512Bytes) auf MMC/SD-Karte
+ for ( uint16_t a = 0; a < 512; a++ ) {
+ mmc_write_byte ( *Buffer++ );
+ }
+
+ //CRC-Byte schreiben
+ mmc_write_byte ( 0xFF ); //Schreibt Dummy CRC
+ mmc_write_byte ( 0xFF ); //CRC Code wird nicht benutzt
+
+ //Fehler beim schreiben? (Data Response XXX00101 = OK)
+ if ( ( mmc_read_byte() & 0x1F ) != 0x05 ) return ( 1 );
+
+ //Wartet auf MMC/SD-Karte Bussy
+ while ( mmc_read_byte() != 0xff ) {};
+
+ //set MMC_Chip_Select to high (MMC/SD-Karte Inaktiv)
+ MMC_Disable();
+
+ return ( 0 );
+}
+
+//############################################################################
+//Routine zum lesen des CID Registers von der MMC/SD-Karte (16Bytes)
+void mmc_read_block ( uint8_t *cmd, uint8_t *Buffer, uint16_t Bytes )
+//############################################################################
+{
+ //Sendet Commando cmd an MMC/SD-Karte
+ if ( mmc_write_command ( cmd ) != 0 ) {
+ return;
+ }
+
+ //Wartet auf Start Byte von der MMC/SD-Karte (FEh/Start Byte)
+ while ( mmc_read_byte() != 0xfe ) {};
+
+ //Lesen des Bolcks (normal 512Bytes) von MMC/SD-Karte
+ for ( uint16_t a = 0; a < Bytes; a++ ) {
+ *Buffer++ = mmc_read_byte();
+ }
+ //CRC-Byte auslesen
+ mmc_read_byte();//CRC - Byte wird nicht ausgewertet
+ mmc_read_byte();//CRC - Byte wird nicht ausgewertet
+
+ //set MMC_Chip_Select to high (MMC/SD-Karte Inaktiv)
+ MMC_Disable();
+
+ return;
+}
+
+//############################################################################
+//Routine zum lesen eines Blocks(512Byte) von der MMC/SD-Karte
+uint8_t mmc_read_sector ( uint32_t addr, uint8_t *Buffer )
+//############################################################################
+{
+ //Commando 16 zum lesen eines Blocks von der MMC/SD - Karte
+ uint8_t cmd[] = {0x51, 0x00, 0x00, 0x00, 0x00, 0xFF};
+
+ /*Die Adressierung der MMC/SD-Karte wird in Bytes angegeben,
+ addr wird von Blocks zu Bytes umgerechnet danach werden
+ diese in das Commando eingefügt*/
+
+ addr = addr << 9; //addr = addr * 512
+
+ cmd[1] = ( ( addr & 0xFF000000 ) >> 24 );
+ cmd[2] = ( ( addr & 0x00FF0000 ) >> 16 );
+ cmd[3] = ( ( addr & 0x0000FF00 ) >> 8 );
+
+ mmc_read_block ( cmd, Buffer, 512 );
+
+ return ( 0 );
+}
+
+//############################################################################
+//Routine zum lesen des CID Registers von der MMC/SD-Karte (16Bytes)
+uint8_t mmc_read_cid ( uint8_t *Buffer )
+//############################################################################
+{
+ //Commando zum lesen des CID Registers
+ uint8_t cmd[] = {0x4A, 0x00, 0x00, 0x00, 0x00, 0xFF};
+
+ mmc_read_block ( cmd, Buffer, 16 );
+
+ return ( 0 );
+}
+
+//############################################################################
+//Routine zum lesen des CSD Registers von der MMC/SD-Karte (16Bytes)
+uint8_t mmc_read_csd ( uint8_t *Buffer )
+//############################################################################
+{
+ //Commando zum lesen des CSD Registers
+ uint8_t cmd[] = {0x49, 0x00, 0x00, 0x00, 0x00, 0xFF};
+
+ mmc_read_block ( cmd, Buffer, 16 );
+
+ return ( 0 );
+}
diff --git a/P8000_WDC_Emulator/P8000_WDC_Emulator/wdc_drv_mmc.h b/P8000_WDC_Emulator/P8000_WDC_Emulator/wdc_drv_mmc.h
new file mode 100644
index 0000000..0bff449
--- /dev/null
+++ b/P8000_WDC_Emulator/P8000_WDC_Emulator/wdc_drv_mmc.h
@@ -0,0 +1,48 @@
+/*#######################################################################################
+Connect ARM to MMC/SD
+
+Copyright (C) 2004 Ulrich Radig
+#######################################################################################*/
+
+#ifndef _MMC_H_
+#define _MMC_H_
+
+#include
+
+#define SPI_Mode 1 //1 = Hardware SPI | 0 = Software SPI
+//#define SPI_Mode 0
+
+#define MMC_Write PORTB //Port an der die MMC/SD-Karte angeschlossen ist also des SPI
+#define MMC_Read PINB
+#define MMC_Direction_REG DDRB
+
+#define SPI_DI 6 //Port Pin an dem Data Output der MMC/SD-Karte angeschlossen ist
+#define SPI_DO 5 //Port Pin an dem Data Input der MMC/SD-Karte angeschlossen ist
+#define SPI_Clock 7 //Port Pin an dem die Clock der MMC/SD-Karte angeschlossen ist (clk)
+#define MMC_Chip_Select 4 //Port Pin an dem Chip Select der MMC/SD-Karte angeschlossen ist
+
+//Prototypes
+
+extern uint8_t mmc_read_byte ( void );
+extern void mmc_write_byte ( uint8_t );
+extern void mmc_read_block ( uint8_t *, uint8_t *, uint16_t );
+
+extern uint8_t mmc_init ( void );
+extern uint8_t mmc_read_sector ( uint32_t, uint8_t * );
+extern uint8_t mmc_write_sector ( uint32_t, uint8_t * );
+
+extern uint8_t mmc_write_command ( uint8_t * );
+extern uint8_t mmc_read_csd ( uint8_t * );
+extern uint8_t mmc_read_cid ( uint8_t * );
+
+//set MMC_Chip_Select to high (MMC/SD-Karte Inaktiv)
+#define MMC_Disable() MMC_Write|= (1<
@@ -15,7 +20,6 @@
#include "wdc_if_pio.h"
#include "wdc_if_sdcard.h"
-
#define DEBUG 1
void atmega_setup ( void );
@@ -23,13 +27,33 @@ int main ( void )
{
uint16_t cmd_counter = 9;
uint16_t data_counter;
+ uint32_t blockno;
+ uint8_t errorcode;
uint8_t *data_buffer = NULL;
uint8_t *cmd_buffer = NULL;
+ uint8_t i8;
+ uint16_t i16;
atmega_setup();
uart_puts_p ( PSTR ( "P8000 WDC Emulator 0.01\n" ) );
+ /* load Parameter Table into RAM if valid */
+ blockno = 0;
+ data_counter = 512;
+ data_buffer = malloc ( data_counter * sizeof ( *data_buffer ) );
+ while ( wdc_read_sector ( blockno, data_buffer ) ) {
+#if DEBUG >= 1
+ uart_puts_p ( PSTR ( "Block 0 of SD-Card not readable" ) );
+#endif
+ }
+
+ if ( data_buffer[0] == 'W' &&
+ data_buffer[1] == 'D' &&
+ data_buffer[2] == 'C' ) {
+ wdc_write_par_table ( data_buffer, data_counter );
+ };
+
while ( 1 ) {
wdc_wait_for_reset();
@@ -40,9 +64,8 @@ int main ( void )
, cmd_counter
);
-
-#ifdef DEBUG
- uart_puts_p ( PSTR ( " CMD Buffer:" ) );
+#if DEBUG == 2
+ uart_puts_p ( PSTR ( " CMD:" ) );
uart_putc_hex ( cmd_buffer[0] );
uart_putc_hex ( cmd_buffer[1] );
uart_putc_hex ( cmd_buffer[2] );
@@ -95,8 +118,8 @@ int main ( void )
data_counter = ( cmd_buffer[7] << 8 ) | cmd_buffer[6];
data_buffer = malloc ( data_counter * sizeof ( *data_buffer ) );
- wdc_read_partab ( data_buffer
- , data_counter );
+ wdc_read_par_table ( data_buffer
+ , data_counter );
wdc_send_data ( data_buffer
, data_counter
@@ -114,15 +137,15 @@ int main ( void )
, data_counter
);
- wdc_write_partab ( data_buffer
- , data_counter );
+ wdc_write_wdc_par ( data_buffer
+ , data_counter );
free ( data_buffer );
break;
case CMD_DL_BTTAB:
- wdc_del_bttab();
+ wdc_del_wdc_btt();
break;
case CMD_RD_BTTAB:
@@ -130,8 +153,8 @@ int main ( void )
data_counter = ( cmd_buffer[7] << 8 ) | cmd_buffer[6];
data_buffer = malloc ( data_counter * sizeof ( *data_buffer ) );
- wdc_read_bttab ( data_buffer
- , data_counter );
+ wdc_read_wdc_btt ( data_buffer
+ , data_counter );
wdc_send_data ( data_buffer
, data_counter
@@ -149,18 +172,140 @@ int main ( void )
, data_counter
);
- wdc_write_bttab ( data_buffer
- , data_counter );
+ wdc_write_wdc_btt ( data_buffer
+ , data_counter );
free ( data_buffer );
break;
- default:
+ case CMD_FMT_BTT:
+ data_counter = 512;
+ data_buffer = calloc ( data_counter, sizeof ( *data_buffer ) );
+
+ blockno = wdc_get_blockno ( cmd_buffer[2] | ( cmd_buffer[3] << 8 )
+ , cmd_buffer[4]
+ , cmd_buffer[5]
+ );
+
+ errorcode = 1;
+ for ( i8 = 0; i8 < wdc_get_hdd_sectors(); i8++ ) {
+ errorcode = wdc_write_sector ( blockno, data_buffer );
+ if ( errorcode ) break;
+ blockno++;
+ }
+
+ if ( errorcode ) {
+ if ( wdc_add_btt_entry ( cmd_buffer[2] | ( cmd_buffer[3] << 8 ), cmd_buffer[4] ) ) {
+ wdc_send_error();
+ } else {
+ free ( data_buffer );
+ data_buffer = malloc ( 3 * sizeof ( *data_buffer ) );
+ data_buffer[0] = cmd_buffer[2]; // Track Low
+ data_buffer[1] = cmd_buffer[3]; // Track High
+ data_buffer[2] = cmd_buffer[4]; // Head
+
+ wdc_send_data ( data_buffer
+ , 3
+ );
+ }
+ }
+
+ free ( data_buffer );
+ break;
+
+ case CMD_ST_PARBTT:
+
+ blockno = 0;
+
+ data_counter = 512;
+ data_buffer = malloc ( data_counter * sizeof ( *data_buffer ) );
+ wdc_read_par_table ( data_buffer
+ , data_counter );
+
+ errorcode = wdc_write_sector ( blockno, data_buffer );
+ if ( errorcode )
+ wdc_send_error();
+
+ free ( data_buffer );
+ break;
+
+ case CMD_RD_WDCERR:
+
+ data_counter = ( cmd_buffer[7] << 8 ) | cmd_buffer[6];
+ data_buffer = calloc ( data_counter, sizeof ( *data_buffer ) );
+ wdc_send_data ( data_buffer
+ , data_counter
+ );
+
+ free ( data_buffer );
+ break;
+
+ case CMD_VER_TRACK:
+
+ data_counter = 512;
+ data_buffer = calloc ( data_counter, sizeof ( *data_buffer ) );
+
+ blockno = wdc_get_blockno ( cmd_buffer[2] | ( cmd_buffer[3] << 8 )
+ , cmd_buffer[4]
+ , cmd_buffer[5]
+ );
+
+ errorcode = 1;
+ for ( i8 = 0; i8 < wdc_get_hdd_sectors(); i8++ ) {
+ errorcode = wdc_read_sector ( blockno, data_buffer );
+ if ( errorcode ) break;
+ blockno++;
+ }
+
+ if ( errorcode )
+ wdc_send_error();
+
+ free ( data_buffer );
+ break;
+
+ case CMD_RD_SECTOR:
+
+ data_counter = ( cmd_buffer[7] << 8 ) | cmd_buffer[6];
+ if ( data_counter % 512 > 0 )
+ data_buffer = malloc ( ( data_counter + 512 - ( data_counter % 512 ) ) * sizeof ( *data_buffer ) );
+ else
+ data_buffer = malloc ( data_counter * sizeof ( *data_buffer ) );
+
+ blockno = wdc_get_blockno ( cmd_buffer[2] | ( cmd_buffer[3] << 8 )
+ , cmd_buffer[4]
+ , cmd_buffer[5]
+ );
+
+ errorcode = 1;
+ for ( i16 = 0; i16 < data_counter; i16 += 512 ) {
+ errorcode = wdc_read_sector ( blockno, data_buffer );
+ if ( errorcode ) break;
+ }
+
+ if ( errorcode )
+ wdc_send_error();
+
+ free ( data_buffer );
+ break;
+
+ default:
+#if DEBUG >= 1
+ uart_puts_p ( PSTR ( " Unknown command:" ) );
+ uart_putc_hex ( cmd_buffer[0] );
+ uart_putc_hex ( cmd_buffer[1] );
+ uart_putc_hex ( cmd_buffer[2] );
+ uart_putc_hex ( cmd_buffer[3] );
+ uart_putc_hex ( cmd_buffer[4] );
+ uart_putc_hex ( cmd_buffer[5] );
+ uart_putc_hex ( cmd_buffer[6] );
+ uart_putc_hex ( cmd_buffer[7] );
+ uart_putc_hex ( cmd_buffer[8] );
+ uart_putc ( '\n' );
+#endif
wdc_send_error();
break;
}
-
free ( cmd_buffer );
}
return 0;
@@ -169,7 +314,12 @@ int main ( void )
void atmega_setup ( void )
{
set_sleep_mode ( SLEEP_MODE_IDLE );
- wdc_init_ports();
- wdc_init_sdcard();
uart_init();
+ wdc_init_ports();
+ while ( wdc_init_sdcard() ) {
+#if DEBUG >= 1
+ uart_puts_p ( PSTR ( "SDCard initialisation failed!" ) );
+#endif
+ }
+
}
\ No newline at end of file
diff --git a/P8000_WDC_Emulator/P8000_WDC_Emulator/wdc_main.h b/P8000_WDC_Emulator/P8000_WDC_Emulator/wdc_main.h
index 97a1381..c5c373a 100644
--- a/P8000_WDC_Emulator/P8000_WDC_Emulator/wdc_main.h
+++ b/P8000_WDC_Emulator/P8000_WDC_Emulator/wdc_main.h
@@ -1,7 +1,7 @@
/*
* P8000 WDC Emulator
*
- * $Id: wdc_main.h,v 1.5 2012/05/31 20:21:51 olivleh1 Exp $
+ * $Id: wdc_main.h,v 1.6 2012/06/02 00:51:55 olivleh1 Exp $
*
*/
@@ -9,12 +9,17 @@
#ifndef MAIN_H_
#define MAIN_H_
-#define CMD_WR_WDC_RAM 0x18 /* P8000 Command: write data to WDC RAM */
-#define CMD_RD_WDC_RAM 0x08 /* P8000 Command: read data from WDC RAM */
-#define CMD_RD_PARTAB 0x28 /* P8000 Command: read Parameter block from WDC RAM */
-#define CMD_WR_PARTAB 0x78 /* P8000 Command: write Parameter block to WDC RAM */
-#define CMD_DL_BTTAB 0x48 /* P8000 Command: delete Bad Track Table from WDC RAM */
-#define CMD_RD_BTTAB 0x58 /* P8000 Command: read Bad Track Table from WDC RAM */
-#define CMD_WR_BTTAB 0x68 /* P8000 Command: write Bad Track Table to WDC RAM */
+#define CMD_WR_WDC_RAM 0x18 /* write data to WDC RAM */
+#define CMD_RD_WDC_RAM 0x08 /* read data from WDC RAM */
+#define CMD_RD_PARTAB 0x28 /* read Parameter block from WDC RAM */
+#define CMD_WR_PARTAB 0x78 /* write Parameter block to WDC RAM */
+#define CMD_DL_BTTAB 0x48 /* delete Bad Track Table from WDC RAM */
+#define CMD_RD_BTTAB 0x58 /* read Bad Track Table from WDC RAM */
+#define CMD_WR_BTTAB 0x68 /* write Bad Track Table to WDC RAM */
+#define CMD_FMT_BTT 0x24 /* format a track and provide BTT info */
+#define CMD_ST_PARBTT 0xC2 /* store PAR and BTT on harddisk */
+#define CMD_RD_WDCERR 0x38 /* read error statistics */
+#define CMD_VER_TRACK 0x44 /* verify track */
+#define CMD_RD_SECTOR 0x01 /* read data beginning at given sector */
#endif /* MAIN_H_ */
diff --git a/P8000_WDC_Emulator/P8000_WDC_Emulator/wdc_ram.c b/P8000_WDC_Emulator/P8000_WDC_Emulator/wdc_ram.c
index 9cb1930..abc0c56 100644
--- a/P8000_WDC_Emulator/P8000_WDC_Emulator/wdc_ram.c
+++ b/P8000_WDC_Emulator/P8000_WDC_Emulator/wdc_ram.c
@@ -1,20 +1,19 @@
/*
* P8000 WDC Emulator
*
- * $Id: wdc_ram.c,v 1.2 2012/05/31 20:34:11 olivleh1 Exp $
+ * $Id: wdc_ram.c,v 1.3 2012/06/02 00:51:55 olivleh1 Exp $
*
*/
#include
+#include "wdc_ram.h"
-uint8_t par_table[200] = { 'W', 'D', 'C', '_', '4', '.', '2', 0x00, 'R', 'O', 'B', ' ', 'K', '5', '5', '0',
- '4', '.', '5', '0', 0x00, 0x00, 0x00, 0x00, 0x04, 0x05, 0x12, 0x00, 0x04, 0x01, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x01, 0x00, 0x01, 0x01,
- 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- };
-uint8_t bt_table[125];
uint8_t wdc_ram[2048];
-
+uint8_t par_table[512] = {'W', 'D', 'C', '_', '4', '.', '2', 0x00, 'R', 'O', 'B', ' ', 'K', '5', '5', '0',
+ '4', '.', '5', '0', 0x00, 0x00, 0x00, 0x00, 0x04, 0x05, 0x12, 0x00, 0x04, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa5, 0x67, 0x01, 0x00, 0x01, 0x01,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
void wdc_write_data_to_ram ( uint8_t *buffer, uint16_t address, uint16_t count )
{
@@ -32,7 +31,8 @@ void wdc_read_data_from_ram ( uint8_t *buffer, uint16_t address, uint16_t count
} while ( count > 0 );
}
-void wdc_read_partab ( uint8_t *buffer, uint16_t count )
+
+void wdc_read_par_table ( uint8_t *buffer, uint16_t count )
{
do {
count--;
@@ -40,33 +40,87 @@ void wdc_read_partab ( uint8_t *buffer, uint16_t count )
} while ( count > 0 );
}
-void wdc_write_partab ( uint8_t *buffer, uint16_t count )
+void wdc_write_par_table ( uint8_t *buffer, uint16_t count )
{
do {
count--;
- par_table[count + 8] = buffer[count];
+ par_table[count] = buffer[count];
} while ( count > 0 );
}
-void wdc_del_bttab()
+
+void wdc_read_wdc_par ( uint8_t *buffer, uint16_t count )
+{
+ do {
+ count--;
+ buffer[count] = par_table[count + POS_PAR_WDC_PAR];
+ } while ( count > 0 );
+}
+
+void wdc_write_wdc_par ( uint8_t *buffer, uint16_t count )
+{
+ do {
+ count--;
+ par_table[count + POS_PAR_WDC_PAR] = buffer[count];
+ } while ( count > 0 );
+}
+
+void wdc_del_wdc_btt()
{
uint8_t i;
for ( i = 0; i < 125; i++ )
- bt_table[i] = 0x00;
+ par_table[i + POS_PAR_WDC_BTT] = 0x00;
+ par_table[122 + POS_PAR_WDC_BTT] = 0xff;
}
-void wdc_read_bttab ( uint8_t *buffer, uint16_t count )
+void wdc_read_wdc_btt ( uint8_t *buffer, uint16_t count )
{
do {
count--;
- buffer[count] = bt_table[count];
+ buffer[count] = par_table[count + POS_PAR_WDC_BTT];
} while ( count > 0 );
}
-void wdc_write_bttab ( uint8_t *buffer, uint16_t count )
+void wdc_write_wdc_btt ( uint8_t *buffer, uint16_t count )
{
do {
count--;
- bt_table[count] = buffer[count];
+ par_table[count + POS_PAR_WDC_BTT] = buffer[count];
} while ( count > 0 );
+}
+
+uint16_t wdc_get_btt_count()
+{
+ return ( ( par_table[0 + POS_PAR_WDC_BTT] | ( par_table[1 + POS_PAR_WDC_BTT] << 8 ) ) );
+}
+
+void wdc_set_btt_count ( uint16_t btt_count )
+{
+ par_table[0 + POS_PAR_WDC_BTT] = ( uint8_t ) btt_count;
+ par_table[1 + POS_PAR_WDC_BTT] = ( btt_count >> 8 );
+}
+
+uint8_t wdc_add_btt_entry ( uint16_t cylinder, uint8_t head )
+{
+ uint16_t btt_count = wdc_get_btt_count();
+
+ if ( btt_count < 120 ) {
+ /* +2 because btt_count is just the amount of bytes for the BTT - but in front of it, there are two bytes */
+ /* storing the amount of bytes for the BTT */
+ par_table[btt_count + 2 + POS_PAR_WDC_BTT] = ( cylinder >> 8 );
+ btt_count++;
+ par_table[btt_count + 2 + POS_PAR_WDC_BTT] = ( uint8_t ) cylinder;
+ btt_count++;
+ par_table[btt_count + 2 + POS_PAR_WDC_BTT] = ( uint8_t ) head;
+ btt_count++;
+ wdc_set_btt_count ( btt_count );
+ return ( 0 );
+ } else {
+ return ( 1 );
+ }
+}
+
+uint8_t wdc_get_hdd_sectors()
+{
+ return ( par_table[18 + POS_PAR_WDC_PAR] );
}
\ No newline at end of file
diff --git a/P8000_WDC_Emulator/P8000_WDC_Emulator/wdc_ram.h b/P8000_WDC_Emulator/P8000_WDC_Emulator/wdc_ram.h
index 5213aa9..40f7d6b 100644
--- a/P8000_WDC_Emulator/P8000_WDC_Emulator/wdc_ram.h
+++ b/P8000_WDC_Emulator/P8000_WDC_Emulator/wdc_ram.h
@@ -1,7 +1,7 @@
/*
* P8000 WDC Emulator
*
- * $Id: wdc_ram.h,v 1.1 2012/05/31 20:21:51 olivleh1 Exp $
+ * $Id: wdc_ram.h,v 1.2 2012/06/02 00:51:55 olivleh1 Exp $
*
*/
@@ -11,13 +11,28 @@
void wdc_write_data_to_ram ( uint8_t *buffer, uint16_t address, uint16_t count );
void wdc_read_data_from_ram ( uint8_t *buffer, uint16_t address, uint16_t count );
-void wdc_read_partab ( uint8_t *buffer, uint16_t count );
-void wdc_write_partab ( uint8_t *buffer, uint16_t count );
+void wdc_read_par_table ( uint8_t *buffer, uint16_t count );
+void wdc_write_par_table ( uint8_t *buffer, uint16_t count );
-void wdc_del_bttab();
-void wdc_read_bttab ( uint8_t *buffer, uint16_t count );
-void wdc_write_bttab ( uint8_t *buffer, uint16_t count );
+void wdc_read_wdc_par ( uint8_t *buffer, uint16_t count );
+void wdc_write_wdc_par ( uint8_t *buffer, uint16_t count );
+
+void wdc_del_wdc_btt();
+void wdc_read_wdc_btt ( uint8_t *buffer, uint16_t count );
+void wdc_write_wdc_btt ( uint8_t *buffer, uint16_t count );
+uint16_t wdc_get_btt_count();
+uint8_t wdc_add_btt_entry ( uint16_t cylinder, uint8_t head );
+
+uint8_t wdc_get_hdd_sectors();
#define convert_ram_address(x) ((x) - 0x2000) /* The S-RAM of the original WDC hardware starts at 0x2000. We use an array as RAM here and no direct RAM access */
+#define POS_PAR_VERSION 0
+#define POS_PAR_WDC_PAR 8
+#define POS_PAR_WDC_BTT 88
+
+#define SIZE_PAR_VERSION 8
+#define SIZE_PAR_WDC_PAR 80
+#define SIZE_PAR_WDC_BTT 125
+
#endif /* WDC_RAM_H_ */
\ No newline at end of file