From a25e66b4ff62f7ccb61b17571230a59bc84454a5 Mon Sep 17 00:00:00 2001 From: Oliver Lehmann Date: Sat, 2 Jun 2012 00:51:55 +0000 Subject: [PATCH] much more support now --- .../P8000_WDC_Emulator/Debug/Makefile | 9 +- .../P8000_WDC_Emulator/Debug/makedep.mk | 2 + .../P8000_WDC_Emulator.cproj | 49 +-- .../P8000_WDC_Emulator/wdc_drv_mmc.c | 302 ++++++++++++++++++ .../P8000_WDC_Emulator/wdc_drv_mmc.h | 48 +++ .../P8000_WDC_Emulator/wdc_if_disk.c | 32 +- .../P8000_WDC_Emulator/wdc_if_disk.h | 7 +- .../P8000_WDC_Emulator/wdc_if_p8000.h | 8 +- .../P8000_WDC_Emulator/wdc_main.c | 186 +++++++++-- .../P8000_WDC_Emulator/wdc_main.h | 21 +- .../P8000_WDC_Emulator/wdc_ram.c | 88 ++++- .../P8000_WDC_Emulator/wdc_ram.h | 27 +- 12 files changed, 698 insertions(+), 81 deletions(-) create mode 100644 P8000_WDC_Emulator/P8000_WDC_Emulator/wdc_drv_mmc.c create mode 100644 P8000_WDC_Emulator/P8000_WDC_Emulator/wdc_drv_mmc.h 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