much more support now

This commit is contained in:
Oliver Lehmann 2012-06-02 00:51:55 +00:00
parent 9c672773b2
commit a25e66b4ff
12 changed files with 698 additions and 81 deletions

View File

@ -36,6 +36,7 @@ SUBDIRS :=
# Add inputs and outputs from these tool invocations to the build variables # Add inputs and outputs from these tool invocations to the build variables
C_SRCS += \ C_SRCS += \
../main.c \ ../main.c \
../mmc.c \
../uart.c \ ../uart.c \
../wdc_if_pio.c \ ../wdc_if_pio.c \
../wdc_if_sdcard.c \ ../wdc_if_sdcard.c \
@ -50,6 +51,7 @@ ASM_SRCS +=
OBJS += \ OBJS += \
main.o \ main.o \
mmc.o \
uart.o \ uart.o \
wdc_if_pio.o \ wdc_if_pio.o \
wdc_if_sdcard.o \ wdc_if_sdcard.o \
@ -58,6 +60,7 @@ wdc_ram.o
OBJS_AS_ARGS += \ OBJS_AS_ARGS += \
main.o \ main.o \
mmc.o \
uart.o \ uart.o \
wdc_if_pio.o \ wdc_if_pio.o \
wdc_if_sdcard.o \ wdc_if_sdcard.o \
@ -66,6 +69,7 @@ wdc_ram.o
C_DEPS += \ C_DEPS += \
main.d \ main.d \
mmc.d \
uart.d \ uart.d \
wdc_if_pio.d \ wdc_if_pio.d \
wdc_if_sdcard.d \ wdc_if_sdcard.d \
@ -74,6 +78,7 @@ wdc_ram.d
C_DEPS_AS_ARGS += \ C_DEPS_AS_ARGS += \
main.d \ main.d \
mmc.d \
uart.d \ uart.d \
wdc_if_pio.d \ wdc_if_pio.d \
wdc_if_sdcard.d \ wdc_if_sdcard.d \
@ -100,10 +105,12 @@ OUTPUT_FILE_DEP:= ./makedep.mk
./%.o: .././%.c ./%.o: .././%.c
@echo Building file: $< @echo Building file: $<
@echo Invoking: AVR/GNU C Compiler : (AVR_8_bit_GNU_Toolchain_3.4.0_663) 4.6.2 @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: $< @echo Finished building: $<

View File

@ -4,6 +4,8 @@
main.c main.c
mmc.c
uart.c uart.c
wdc_if_pio.c wdc_if_pio.c

View File

@ -45,28 +45,27 @@
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<ToolchainSettings> <ToolchainSettings>
<AvrGcc> <AvrGcc>
<avrgcc.common.outputfiles.hex>True</avrgcc.common.outputfiles.hex> <avrgcc.common.outputfiles.hex>True</avrgcc.common.outputfiles.hex>
<avrgcc.common.outputfiles.lss>True</avrgcc.common.outputfiles.lss> <avrgcc.common.outputfiles.lss>True</avrgcc.common.outputfiles.lss>
<avrgcc.common.outputfiles.eep>True</avrgcc.common.outputfiles.eep> <avrgcc.common.outputfiles.eep>True</avrgcc.common.outputfiles.eep>
<avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned> <avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>
<avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned> <avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>
<avrgcc.compiler.optimization.level>Optimize (-O1)</avrgcc.compiler.optimization.level> <avrgcc.compiler.optimization.level>Optimize (-O1)</avrgcc.compiler.optimization.level>
<avrgcc.compiler.optimization.PackStructureMembers>True</avrgcc.compiler.optimization.PackStructureMembers> <avrgcc.compiler.optimization.PackStructureMembers>True</avrgcc.compiler.optimization.PackStructureMembers>
<avrgcc.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcc.compiler.optimization.AllocateBytesNeededForEnum> <avrgcc.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcc.compiler.optimization.AllocateBytesNeededForEnum>
<avrgcc.compiler.optimization.DebugLevel>Default (-g2)</avrgcc.compiler.optimization.DebugLevel> <avrgcc.compiler.optimization.DebugLevel>Default (-g2)</avrgcc.compiler.optimization.DebugLevel>
<avrgcc.compiler.warnings.AllWarnings>True</avrgcc.compiler.warnings.AllWarnings> <avrgcc.compiler.warnings.AllWarnings>True</avrgcc.compiler.warnings.AllWarnings>
<avrgcc.compiler.warnings.Undefined>True</avrgcc.compiler.warnings.Undefined> <avrgcc.compiler.warnings.Undefined>True</avrgcc.compiler.warnings.Undefined>
<avrgcc.compiler.warnings.WarningsAsErrors>True</avrgcc.compiler.warnings.WarningsAsErrors> <avrgcc.compiler.warnings.WarningsAsErrors>True</avrgcc.compiler.warnings.WarningsAsErrors>
<avrgcc.compiler.warnings.Pedantic>True</avrgcc.compiler.warnings.Pedantic> <avrgcc.compiler.warnings.Pedantic>True</avrgcc.compiler.warnings.Pedantic>
<avrgcc.compiler.warnings.PedanticWarningsAsErrors>True</avrgcc.compiler.warnings.PedanticWarningsAsErrors> <avrgcc.compiler.warnings.PedanticWarningsAsErrors>True</avrgcc.compiler.warnings.PedanticWarningsAsErrors>
<avrgcc.compiler.miscellaneous.DoNotDeleteTemporaryFiles>True</avrgcc.compiler.miscellaneous.DoNotDeleteTemporaryFiles> <avrgcc.linker.libraries.Libraries>
<avrgcc.linker.libraries.Libraries> <ListValues>
<ListValues> <Value>m</Value>
<Value>m</Value> </ListValues>
</ListValues> </avrgcc.linker.libraries.Libraries>
</avrgcc.linker.libraries.Libraries> <avrgcc.assembler.debugging.DebugLevel>Default (-Wa,-g)</avrgcc.assembler.debugging.DebugLevel>
<avrgcc.assembler.debugging.DebugLevel>Default (-Wa,-g)</avrgcc.assembler.debugging.DebugLevel> </AvrGcc>
</AvrGcc>
</ToolchainSettings> </ToolchainSettings>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
@ -79,6 +78,12 @@
<Compile Include="main.h"> <Compile Include="main.h">
<SubType>compile</SubType> <SubType>compile</SubType>
</Compile> </Compile>
<Compile Include="mmc.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="mmc.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="uart.c"> <Compile Include="uart.c">
<SubType>compile</SubType> <SubType>compile</SubType>
</Compile> </Compile>

View File

@ -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 );
}

View File

@ -0,0 +1,48 @@
/*#######################################################################################
Connect ARM to MMC/SD
Copyright (C) 2004 Ulrich Radig
#######################################################################################*/
#ifndef _MMC_H_
#define _MMC_H_
#include <avr/io.h>
#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<<MMC_Chip_Select);
//set MMC_Chip_Select to low (MMC/SD-Karte Aktiv)
#define MMC_Enable() MMC_Write&=~(1<<MMC_Chip_Select);
#define nop() __asm__ __volatile__ ("nop" ::)
#endif //_MMC_H_

View File

@ -1,11 +1,37 @@
/* /*
* P8000 WDC Emulator * P8000 WDC Emulator
* *
* $Id: wdc_if_disk.c,v 1.1 2012/05/31 20:21:51 olivleh1 Exp $ * $Id: wdc_if_disk.c,v 1.2 2012/06/02 00:51:55 olivleh1 Exp $
* *
*/ */
void wdc_init_sdcard() #include "mmc.h"
extern uint8_t par_table[200];
uint8_t wdc_init_sdcard()
{ {
asm("nop"); return mmc_init();
}
uint32_t wdc_get_blockno ( uint16_t req_cylinder, uint8_t req_head, uint8_t req_sector )
{
/* TODO: no direct access of par_table - use getter functions instead - but only after speed is sufficient */
/* +-------------------------------------------------------------- requested cylinder from P8000
* | +----------------------------------------------- configured heads form the harddisk
* | | +------------------------------- configured sectors for the harddisk
* | | | +-------------- requested head from P8000
* | | | | +-- configured sectors for the harddisk
* | | | | | +---- requested sector from P8000 - 1 as we start counting with 0
* | | | | | | */
return ( ( req_cylinder * par_table[25] * par_table[26] ) + ( req_head * par_table[26] ) + ( req_sector - 1 ) );
}
uint8_t wdc_write_sector ( uint16_t addr, uint8_t *sector )
{
return mmc_write_sector ( addr, sector );
}
uint8_t wdc_read_sector ( uint16_t addr, uint8_t *sector )
{
return mmc_read_sector ( addr, sector );
} }

View File

@ -1,13 +1,16 @@
/* /*
* P8000 WDC Emulator * P8000 WDC Emulator
* *
* $Id: wdc_if_disk.h,v 1.1 2012/05/31 20:21:51 olivleh1 Exp $ * $Id: wdc_if_disk.h,v 1.2 2012/06/02 00:51:55 olivleh1 Exp $
* *
*/ */
#ifndef WDC_IF_SDCARD_H_ #ifndef WDC_IF_SDCARD_H_
#define WDC_IF_SDCARD_H_ #define WDC_IF_SDCARD_H_
void wdc_init_sdcard(); uint8_t wdc_init_sdcard();
uint32_t wdc_get_blockno ( uint16_t req_cylinder, uint8_t req_head, uint8_t req_sector );
uint8_t wdc_write_sector ( uint16_t addr, uint8_t *sector );
uint8_t wdc_read_sector ( uint16_t addr, uint8_t *sector );
#endif /* WDC_IF_SDCARD_H_ */ #endif /* WDC_IF_SDCARD_H_ */

View File

@ -1,7 +1,7 @@
/* /*
* P8000 WDC Emulator * P8000 WDC Emulator
* *
* $Id: wdc_if_p8000.h,v 1.1 2012/05/31 20:21:51 olivleh1 Exp $ * $Id: wdc_if_p8000.h,v 1.2 2012/06/02 00:51:55 olivleh1 Exp $
* *
*/ */
@ -45,9 +45,9 @@
void wdc_init_ports(); void wdc_init_ports();
void wdc_wait_for_reset(); void wdc_wait_for_reset();
void wdc_receive_cmd(uint8_t *buffer, uint16_t count); void wdc_receive_cmd ( uint8_t *buffer, uint16_t count );
void wdc_receive_data(uint8_t *buffer, uint16_t count); void wdc_receive_data ( uint8_t *buffer, uint16_t count );
void wdc_send_data(uint8_t *buffer, uint16_t count); void wdc_send_data ( uint8_t *buffer, uint16_t count );
void wdc_send_error(); void wdc_send_error();
#endif /* WDC_IF_PIO_H_ */ #endif /* WDC_IF_PIO_H_ */

View File

@ -1,8 +1,13 @@
/* /*
* P8000 WDC Emulator * P8000 WDC Emulator
* *
* $Id: wdc_main.c,v 1.5 2012/05/31 20:21:51 olivleh1 Exp $ * $Id: wdc_main.c,v 1.6 2012/06/02 00:51:55 olivleh1 Exp $
* *
* TODO: - Prio 1: more commandcodes
* - Prio 2: check if BTT is really cleaned when sa.format gets called all the time with a real drive
* - Prio 2: respect BTT entries when calculating the block number to use.
* - Prio 3: work out how PAR+BTT where originally stored on the harddisks and store them the same way
* - Prio 3: put the whole par_table handling from wdc_ram.[ch] into wdc_par.[ch]
*/ */
#include <string.h> #include <string.h>
@ -15,7 +20,6 @@
#include "wdc_if_pio.h" #include "wdc_if_pio.h"
#include "wdc_if_sdcard.h" #include "wdc_if_sdcard.h"
#define DEBUG 1 #define DEBUG 1
void atmega_setup ( void ); void atmega_setup ( void );
@ -23,13 +27,33 @@ int main ( void )
{ {
uint16_t cmd_counter = 9; uint16_t cmd_counter = 9;
uint16_t data_counter; uint16_t data_counter;
uint32_t blockno;
uint8_t errorcode;
uint8_t *data_buffer = NULL; uint8_t *data_buffer = NULL;
uint8_t *cmd_buffer = NULL; uint8_t *cmd_buffer = NULL;
uint8_t i8;
uint16_t i16;
atmega_setup(); atmega_setup();
uart_puts_p ( PSTR ( "P8000 WDC Emulator 0.01\n" ) ); 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 ) { while ( 1 ) {
wdc_wait_for_reset(); wdc_wait_for_reset();
@ -40,9 +64,8 @@ int main ( void )
, cmd_counter , cmd_counter
); );
#if DEBUG == 2
#ifdef DEBUG uart_puts_p ( PSTR ( " CMD:" ) );
uart_puts_p ( PSTR ( " CMD Buffer:" ) );
uart_putc_hex ( cmd_buffer[0] ); uart_putc_hex ( cmd_buffer[0] );
uart_putc_hex ( cmd_buffer[1] ); uart_putc_hex ( cmd_buffer[1] );
uart_putc_hex ( cmd_buffer[2] ); uart_putc_hex ( cmd_buffer[2] );
@ -95,8 +118,8 @@ int main ( void )
data_counter = ( cmd_buffer[7] << 8 ) | cmd_buffer[6]; data_counter = ( cmd_buffer[7] << 8 ) | cmd_buffer[6];
data_buffer = malloc ( data_counter * sizeof ( *data_buffer ) ); data_buffer = malloc ( data_counter * sizeof ( *data_buffer ) );
wdc_read_partab ( data_buffer wdc_read_par_table ( data_buffer
, data_counter ); , data_counter );
wdc_send_data ( data_buffer wdc_send_data ( data_buffer
, data_counter , data_counter
@ -114,15 +137,15 @@ int main ( void )
, data_counter , data_counter
); );
wdc_write_partab ( data_buffer wdc_write_wdc_par ( data_buffer
, data_counter ); , data_counter );
free ( data_buffer ); free ( data_buffer );
break; break;
case CMD_DL_BTTAB: case CMD_DL_BTTAB:
wdc_del_bttab(); wdc_del_wdc_btt();
break; break;
case CMD_RD_BTTAB: case CMD_RD_BTTAB:
@ -130,8 +153,8 @@ int main ( void )
data_counter = ( cmd_buffer[7] << 8 ) | cmd_buffer[6]; data_counter = ( cmd_buffer[7] << 8 ) | cmd_buffer[6];
data_buffer = malloc ( data_counter * sizeof ( *data_buffer ) ); data_buffer = malloc ( data_counter * sizeof ( *data_buffer ) );
wdc_read_bttab ( data_buffer wdc_read_wdc_btt ( data_buffer
, data_counter ); , data_counter );
wdc_send_data ( data_buffer wdc_send_data ( data_buffer
, data_counter , data_counter
@ -149,18 +172,140 @@ int main ( void )
, data_counter , data_counter
); );
wdc_write_bttab ( data_buffer wdc_write_wdc_btt ( data_buffer
, data_counter ); , data_counter );
free ( data_buffer ); free ( data_buffer );
break; 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(); wdc_send_error();
break; break;
} }
free ( cmd_buffer ); free ( cmd_buffer );
} }
return 0; return 0;
@ -169,7 +314,12 @@ int main ( void )
void atmega_setup ( void ) void atmega_setup ( void )
{ {
set_sleep_mode ( SLEEP_MODE_IDLE ); set_sleep_mode ( SLEEP_MODE_IDLE );
wdc_init_ports();
wdc_init_sdcard();
uart_init(); uart_init();
wdc_init_ports();
while ( wdc_init_sdcard() ) {
#if DEBUG >= 1
uart_puts_p ( PSTR ( "SDCard initialisation failed!" ) );
#endif
}
} }

View File

@ -1,7 +1,7 @@
/* /*
* P8000 WDC Emulator * 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_ #ifndef MAIN_H_
#define MAIN_H_ #define MAIN_H_
#define CMD_WR_WDC_RAM 0x18 /* P8000 Command: write data to WDC RAM */ #define CMD_WR_WDC_RAM 0x18 /* write data to WDC RAM */
#define CMD_RD_WDC_RAM 0x08 /* P8000 Command: read data from WDC RAM */ #define CMD_RD_WDC_RAM 0x08 /* read data from WDC RAM */
#define CMD_RD_PARTAB 0x28 /* P8000 Command: read Parameter block from WDC RAM */ #define CMD_RD_PARTAB 0x28 /* read Parameter block from WDC RAM */
#define CMD_WR_PARTAB 0x78 /* P8000 Command: write Parameter block to WDC RAM */ #define CMD_WR_PARTAB 0x78 /* write Parameter block to WDC RAM */
#define CMD_DL_BTTAB 0x48 /* P8000 Command: delete Bad Track Table from WDC RAM */ #define CMD_DL_BTTAB 0x48 /* delete Bad Track Table from WDC RAM */
#define CMD_RD_BTTAB 0x58 /* P8000 Command: read Bad Track Table from WDC RAM */ #define CMD_RD_BTTAB 0x58 /* read Bad Track Table from WDC RAM */
#define CMD_WR_BTTAB 0x68 /* P8000 Command: write Bad Track Table to 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_ */ #endif /* MAIN_H_ */

View File

@ -1,20 +1,19 @@
/* /*
* P8000 WDC Emulator * 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 <avr/pgmspace.h> #include <avr/pgmspace.h>
#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 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 ) 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 ); } 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 { do {
count--; count--;
@ -40,33 +40,87 @@ void wdc_read_partab ( uint8_t *buffer, uint16_t count )
} while ( count > 0 ); } 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 { do {
count--; count--;
par_table[count + 8] = buffer[count]; par_table[count] = buffer[count];
} while ( count > 0 ); } 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; uint8_t i;
for ( i = 0; i < 125; 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 { do {
count--; count--;
buffer[count] = bt_table[count]; buffer[count] = par_table[count + POS_PAR_WDC_BTT];
} while ( count > 0 ); } 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 { do {
count--; count--;
bt_table[count] = buffer[count]; par_table[count + POS_PAR_WDC_BTT] = buffer[count];
} while ( count > 0 ); } 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] );
}

View File

@ -1,7 +1,7 @@
/* /*
* P8000 WDC Emulator * 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_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_data_from_ram ( uint8_t *buffer, uint16_t address, uint16_t count );
void wdc_read_partab ( uint8_t *buffer, uint16_t count ); void wdc_read_par_table ( uint8_t *buffer, uint16_t count );
void wdc_write_partab ( uint8_t *buffer, uint16_t count ); void wdc_write_par_table ( uint8_t *buffer, uint16_t count );
void wdc_del_bttab(); void wdc_read_wdc_par ( uint8_t *buffer, uint16_t count );
void wdc_read_bttab ( uint8_t *buffer, uint16_t count ); void wdc_write_wdc_par ( uint8_t *buffer, uint16_t count );
void wdc_write_bttab ( 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 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_ */ #endif /* WDC_RAM_H_ */