add SDHC support

rework PAR+BTT system to match the original P8000 behaviour
This commit is contained in:
Oliver Lehmann 2012-06-09 00:22:28 +00:00
parent e098003f7d
commit 33783a4bb2
9 changed files with 439 additions and 232 deletions

View File

@ -26,7 +26,7 @@
*/ */
/* /*
* $Id: wdc_config.h,v 1.10 2012/06/08 10:40:39 olivleh1 Exp $ * $Id: wdc_config.h,v 1.11 2012/06/09 00:22:28 olivleh1 Exp $
*/ */
@ -78,6 +78,7 @@
#define MMC_MULTIBLOCK 1 #define MMC_MULTIBLOCK 1
#define MEASURE_SDCARD_TIME 1
#undef MEASURE_SDCARD_TIME #undef MEASURE_SDCARD_TIME
#endif /* CONFIG_H_ */ #endif /* CONFIG_H_ */

View File

@ -26,7 +26,7 @@
*/ */
/* /*
* $Id: wdc_drv_mmc.c,v 1.14 2012/06/08 11:11:26 olivleh1 Exp $ * $Id: wdc_drv_mmc.c,v 1.15 2012/06/09 00:22:28 olivleh1 Exp $
*/ */
#include <avr/io.h> #include <avr/io.h>
@ -45,6 +45,7 @@
#define CMD0 (0x40 + 0) #define CMD0 (0x40 + 0)
#define CMD1 (0x40 + 1) #define CMD1 (0x40 + 1)
#define CMD8 (0x40 + 8)
#define CMD12 (0x40 + 12) #define CMD12 (0x40 + 12)
#define CMD17 (0x40 + 17) #define CMD17 (0x40 + 17)
#define CMD18 (0x40 + 18) #define CMD18 (0x40 + 18)
@ -61,6 +62,8 @@
uint8_t mmc_read_block ( uint8_t *, uint8_t *, uint16_t ); uint8_t mmc_read_block ( uint8_t *, uint8_t *, uint16_t );
uint8_t mmc_cmd ( uint8_t * ); uint8_t mmc_cmd ( uint8_t * );
uint8_t is_sdhc = 0;
typedef union { typedef union {
uint32_t value32; uint32_t value32;
struct { struct {
@ -177,6 +180,7 @@ uint8_t mmc_enable_crc ( uint8_t on_off )
uint8_t mmc_init () uint8_t mmc_init ()
{ {
uint16_t t16 = 0; uint16_t t16 = 0;
uint8_t a;
DDR_MMC &= ~ ( 1 << PIN_MMC_MISO ); DDR_MMC &= ~ ( 1 << PIN_MMC_MISO );
@ -184,7 +188,7 @@ uint8_t mmc_init ()
DDR_MMC |= ( 1 << PIN_MMC_MOSI ); DDR_MMC |= ( 1 << PIN_MMC_MOSI );
DDR_MMC |= ( 1 << PIN_MMC_CS ); DDR_MMC |= ( 1 << PIN_MMC_CS );
for ( uint8_t a = 0; a < 200; a++ ) { for ( a = 0; a < 200; a++ ) {
nop(); nop();
}; };
@ -193,7 +197,7 @@ uint8_t mmc_init ()
MMC_Disable(); MMC_Disable();
for ( uint8_t b = 0; b < 0x0f; b++ ) { for ( a = 0; a < 0x0f; a++ ) {
send_dummy_byte(); send_dummy_byte();
} }
@ -212,12 +216,41 @@ uint8_t mmc_init ()
send_dummy_byte(); send_dummy_byte();
cmd[0] = CMD8;
cmd[1] = 0x00;
cmd[2] = 0x00;
cmd[3] = 0x01;
cmd[4] = 0xaa;
cmd[5] = 0x86;
a = mmc_cmd ( cmd );
/* if SDHC Card */
if ( a <= 1 ) {
/* skip 6 bytes */
for ( a = 0; a < 6; a++ )
send_dummy_byte();
is_sdhc = 1;
/* prepare next cmd */
cmd[0] = CMD1;
cmd[1] = 0x40;
cmd[2] = cmd[3] = cmd[4] = 0x00;
cmd[5] = 0xFF;
} else {
send_dummy_byte();
is_sdhc = 0;
/* prepare next cmd */
cmd[0] = CMD1;
cmd[1] = cmd[2] = cmd[3] = cmd[4] = 0x00;
cmd[5] = 0xFF;
}
/* /*
* send CMD1 * send CMD1
*/ */
t16 = 0; t16 = 0;
cmd[0] = CMD1;
cmd[5] = 0xFF;
while ( mmc_cmd ( cmd ) != 0 ) { while ( mmc_cmd ( cmd ) != 0 ) {
send_dummy_byte(); send_dummy_byte();
if ( t16++ > 1000 ) { if ( t16++ > 1000 ) {
@ -281,11 +314,13 @@ uint8_t mmc_write_sector ( uint32_t addr, uint8_t *buffer )
wait_till_card_ready(); wait_till_card_ready();
/* convert blocks to bytes */ /* convert blocks to bytes */
addr = addr * MMC_BLOCKLEN; if ( !is_sdhc )
addr = addr * MMC_BLOCKLEN;
x.value32 = addr; x.value32 = addr;
cmd[1] = x.value8.hh; cmd[1] = x.value8.hh;
cmd[2] = x.value8.hl; cmd[2] = x.value8.hl;
cmd[3] = x.value8.lh; cmd[3] = x.value8.lh;
cmd[4] = x.value8.ll;
/* /*
* send CMD24 * send CMD24
@ -340,7 +375,7 @@ uint8_t mmc_write_sector ( uint32_t addr, uint8_t *buffer )
uint8_t mmc_read_block ( uint8_t *cmd, uint8_t *buffer, uint16_t bytes ) uint8_t mmc_read_block ( uint8_t *cmd, uint8_t *buffer, uint16_t bytes )
{ {
uint16_t i = 1; uint16_t i = 1;
uint8_t by; uint8_t by;
#ifdef SPI_CRC #ifdef SPI_CRC
uint16_t crc; uint16_t crc;
#endif #endif
@ -373,7 +408,7 @@ uint8_t by;
wait_till_send_done(); wait_till_send_done();
by = recv_byte(); by = recv_byte();
xmit_byte ( 0xff ); xmit_byte ( 0xff );
} while ( i<bytes ); } while ( i < bytes );
*buffer = by; *buffer = by;
@ -382,7 +417,7 @@ uint8_t by;
#ifdef SPI_CRC #ifdef SPI_CRC
crc = recv_byte() << 8; crc = recv_byte() << 8;
xmit_byte ( 0xff ); xmit_byte ( 0xff );
buffer = buffer - (bytes-1); buffer = buffer - ( bytes - 1 );
wait_till_send_done(); wait_till_send_done();
crc |= recv_byte(); crc |= recv_byte();
if ( crc != crc16 ( buffer, bytes ) ) { if ( crc != crc16 ( buffer, bytes ) ) {
@ -407,11 +442,13 @@ uint8_t mmc_read_sector ( uint32_t addr, uint8_t *buffer )
uint8_t cmd[] = {CMD17, 0x00, 0x00, 0x00, 0x00, 0xFF}; uint8_t cmd[] = {CMD17, 0x00, 0x00, 0x00, 0x00, 0xFF};
/* convert blocks to bytes */ /* convert blocks to bytes */
addr = addr * MMC_BLOCKLEN; if ( !is_sdhc )
addr = addr * MMC_BLOCKLEN;
x.value32 = addr; x.value32 = addr;
cmd[1] = x.value8.hh; cmd[1] = x.value8.hh;
cmd[2] = x.value8.hl; cmd[2] = x.value8.hl;
cmd[3] = x.value8.lh; cmd[3] = x.value8.lh;
cmd[4] = x.value8.ll;
return mmc_read_block ( cmd, buffer, MMC_BLOCKLEN ); return mmc_read_block ( cmd, buffer, MMC_BLOCKLEN );
@ -452,14 +489,16 @@ uint8_t mmc_read_multiblock ( uint32_t addr, uint8_t *buffer, uint8_t numblocks
#endif #endif
/* convert blocks to bytes */ /* convert blocks to bytes */
addr = addr * MMC_BLOCKLEN; if ( !is_sdhc )
addr = addr * MMC_BLOCKLEN;
x.value32 = addr; x.value32 = addr;
#ifdef MMC_MULTIBLOCK #ifdef MMC_MULTIBLOCK
cmd[0] = CMD18; cmd[0] = CMD18;
cmd[1] = x.value8.hh; cmd[1] = x.value8.hh;
cmd[2] = x.value8.hl; cmd[2] = x.value8.hl;
cmd[3] = x.value8.lh; cmd[3] = x.value8.lh;
cmd[4] = 0; cmd[4] = x.value8.ll;
wait_till_card_ready(); wait_till_card_ready();
@ -482,6 +521,7 @@ uint8_t mmc_read_multiblock ( uint32_t addr, uint8_t *buffer, uint8_t numblocks
cmd[1] = x.value8.hh; cmd[1] = x.value8.hh;
cmd[2] = x.value8.hl; cmd[2] = x.value8.hl;
cmd[3] = x.value8.lh; cmd[3] = x.value8.lh;
cmd[4] = x.value8.ll;
/* /*
* send CMD17 * send CMD17
@ -592,14 +632,16 @@ uint8_t mmc_write_multiblock ( uint32_t addr, uint8_t *buffer, uint8_t numblocks
#endif #endif
#endif #endif
/* convert blocks to bytes */ /* convert blocks to bytes */
addr = addr * MMC_BLOCKLEN; /* convert blocks to bytes */
if ( !is_sdhc )
addr = addr * MMC_BLOCKLEN;
x.value32 = addr; x.value32 = addr;
#ifdef MMC_MULTIBLOCK #ifdef MMC_MULTIBLOCK
cmd[0] = CMD25; cmd[0] = CMD25;
cmd[1] = x.value8.hh; cmd[1] = x.value8.hh;
cmd[2] = x.value8.hl; cmd[2] = x.value8.hl;
cmd[3] = x.value8.lh; cmd[3] = x.value8.lh;
cmd[4] = 0; cmd[4] = x.value8.ll;
/* /*
* send CMD25 * send CMD25
@ -619,6 +661,7 @@ uint8_t mmc_write_multiblock ( uint32_t addr, uint8_t *buffer, uint8_t numblocks
cmd[1] = x.value8.hh; cmd[1] = x.value8.hh;
cmd[2] = x.value8.hl; cmd[2] = x.value8.hl;
cmd[3] = x.value8.lh; cmd[3] = x.value8.lh;
cmd[4] = x.value8.ll;
/* /*
* send CMD24 * send CMD24

View File

@ -26,7 +26,7 @@
*/ */
/* /*
* $Id: wdc_if_disk.c,v 1.9 2012/06/07 18:01:02 olivleh1 Exp $ * $Id: wdc_if_disk.c,v 1.10 2012/06/09 00:22:28 olivleh1 Exp $
*/ */
#include <stdint.h> #include <stdint.h>
@ -34,8 +34,6 @@
#include "uart.h" #include "uart.h"
#include "wdc_par.h" #include "wdc_par.h"
extern uint8_t par_table[];
uint8_t wdc_init_sdcard() uint8_t wdc_init_sdcard()
{ {
uint8_t errorcode; uint8_t errorcode;

View File

@ -18,7 +18,7 @@
#include "uart.h" #include "uart.h"
#ifdef MEASURE_SDCARD_TIME #ifdef MEASURE_SDCARD_TIME
#define BLOCKNO 150000 #define BLOCKNO 300000
extern uint32_t overflow; extern uint32_t overflow;
@ -108,13 +108,13 @@ void test_read512(uint8_t numblocks, uint8_t nr_of_tests)
uint32_t blockno = 0; uint32_t blockno = 0;
uint8_t i8, errorcode; uint8_t i8, errorcode;
uart_puts_p ( PSTR ( "Test Read 5000 512B-Blocks with Multiblock-Read (4KB Blocksize):" ) ); uart_puts_p ( PSTR ( "Test Read 5000 512B-Blocks with Singleblock-Read (512B Blocksize):" ) );
uart_putc ( '\n' ); uart_putc ( '\n' );
for ( i8 = 0; i8 < nr_of_tests; i8++ ) { for ( i8 = 0; i8 < nr_of_tests; i8++ ) {
blockno = BLOCKNO; blockno = BLOCKNO;
for ( starttime = overflow; blockno < ( BLOCKNO + 5000 ); blockno += numblocks ) { for ( starttime = overflow; blockno < ( BLOCKNO + 5000 ); blockno++ ) {
errorcode = wdc_read_multiblock ( blockno, data_buffer, numblocks ); errorcode = wdc_read_sector ( blockno, data_buffer );
if ( errorcode ) { if ( errorcode ) {
break; break;
} }

View File

@ -26,13 +26,13 @@
*/ */
/* /*
* $Id: wdc_if_p8000.h,v 1.6 2012/06/07 18:01:02 olivleh1 Exp $ * $Id: wdc_if_p8000.h,v 1.7 2012/06/09 00:22:28 olivleh1 Exp $
*/ */
#ifndef WDC_IF_PIO_H_ #ifndef WDC_IF_PIO_H_
#define WDC_IF_PIO_H_ #define WDC_IF_PIO_H_
#define DELAY_PIO_US 500 #define DELAY_PIO_US 450
#define configure_port_data_read() DDR_DATA = 0x00 /* programs the DATA-Port as Input-only for reading from the P8000*/ #define configure_port_data_read() DDR_DATA = 0x00 /* programs the DATA-Port as Input-only for reading from the P8000*/
#define configure_port_data_write() DDR_DATA = 0xff /* programs the DATA-Port as Out-only for writing to the P8000*/ #define configure_port_data_write() DDR_DATA = 0xff /* programs the DATA-Port as Out-only for writing to the P8000*/

View File

@ -29,7 +29,7 @@
/* /*
* P8000 WDC Emulator * P8000 WDC Emulator
* *
* $Id: wdc_main.c,v 1.22 2012/06/08 11:11:26 olivleh1 Exp $ * $Id: wdc_main.c,v 1.23 2012/06/09 00:22:28 olivleh1 Exp $
* *
* TODO: - Different Errorcodes in the MMC layer (use defines) * TODO: - Different Errorcodes in the MMC layer (use defines)
* - errorchecking in several places * - errorchecking in several places
@ -41,6 +41,8 @@
* - Prio 3: put the whole par_table handling from wdc_ram.[ch] into wdc_par.[ch] * - Prio 3: put the whole par_table handling from wdc_ram.[ch] into wdc_par.[ch]
*/ */
#define DEBUG 1
#include <avr/io.h> #include <avr/io.h>
#include <avr/interrupt.h> #include <avr/interrupt.h>
@ -49,15 +51,15 @@
#include <avr/pgmspace.h> #include <avr/pgmspace.h>
#include <avr/sleep.h> #include <avr/sleep.h>
#include "main.h" #include "main.h"
#ifdef DEBUG
#include "uart.h" #include "uart.h"
#endif
#include "wdc_ram.h" #include "wdc_ram.h"
#include "wdc_par.h" #include "wdc_par.h"
#include "wdc_if_pio.h" #include "wdc_if_pio.h"
#include "wdc_if_sdcard.h" #include "wdc_if_sdcard.h"
#include "config.h" #include "config.h"
#define DEBUG 1
void atmega_setup ( void ); void atmega_setup ( void );
#ifdef MEASURE_SDCARD_TIME #ifdef MEASURE_SDCARD_TIME
@ -68,9 +70,13 @@ ISR ( TIMER0_OVF_vect )
overflow ++; overflow ++;
} }
#else #else
/* switched from local to global for keeping an eye on memory usage */ /* switched from local to global for keeping an eye on memory usage */
uint8_t data_buffer[4096]; uint8_t data_buffer[4096];
uint8_t cmd_buffer[9]; uint8_t cmd_buffer[9];
extern uint8_t valid_disk;
#endif #endif
int __attribute__ ( ( OS_main ) ) int __attribute__ ( ( OS_main ) )
@ -92,19 +98,24 @@ main ( void )
#else #else
/* load Parameter Table into RAM if valid */ /* load Parameter Table into RAM if valid */
blockno = 0; if ( wdc_get_disk_valid() ) {
data_counter = WDC_BLOCKLEN; blockno = 0;
while ( wdc_read_sector ( blockno, data_buffer ) ) { data_counter = WDC_BLOCKLEN;
#if DEBUG >= 1 wdc_read_sector ( blockno, data_buffer );
uart_puts_p ( PSTR ( "Block 0 of SD-Card not readable" ) );
#endif
}
if ( data_buffer[0] == 'W' && if ( data_buffer[0] == 'W' &&
data_buffer[1] == 'D' && data_buffer[1] == 'D' &&
data_buffer[2] == 'C' ) { data_buffer[2] == 'C' &&
wdc_write_par_table ( data_buffer, data_counter ); data_buffer[3] == '_' &&
}; data_buffer[4] == '4' &&
data_buffer[5] == '.' &&
data_buffer[6] == '2' ) {
wdc_write_par_table ( data_buffer, data_counter );
wdc_set_disk_valid();
} else {
wdc_set_disk_invalid();
};
}
while ( 1 ) { while ( 1 ) {
@ -132,224 +143,257 @@ main ( void )
#endif #endif
#endif #endif
switch ( cmd_buffer[0] ) { /* if the disk is not valid, only maintenance commands are allowed */
case CMD_WR_BLOCK: if ( ! wdc_get_disk_valid()
data_counter = ( cmd_buffer[7] << 8 ) | cmd_buffer[6]; && cmd_buffer[0] != CMD_RD_WDC_RAM
&& cmd_buffer[0] != CMD_FMTRD_TRACK
&& cmd_buffer[0] != CMD_WR_WDC_RAM
&& cmd_buffer[0] != CMD_FMTBTT_TRACK
&& cmd_buffer[0] != CMD_RD_PARTAB
&& cmd_buffer[0] != CMD_RD_WDCERR
&& cmd_buffer[0] != CMD_VER_TRACK
&& cmd_buffer[0] != CMD_DL_BTTAB
&& cmd_buffer[0] != CMD_RD_BTTAB
&& cmd_buffer[0] != CMD_WR_BTTAB
&& cmd_buffer[0] != CMD_WR_PARTAB
&& cmd_buffer[0] != CMD_ST_PARBTT
) {
wdc_send_error();
} else {
blockno = wdc_p8kblock2sdblock ( ( ( uint32_t ) cmd_buffer[5] << 24 ) | ( ( uint32_t ) cmd_buffer[4] << 16 ) | ( ( uint16_t ) cmd_buffer[3] << 8 ) | cmd_buffer[2] ); switch ( cmd_buffer[0] ) {
wdc_receive_data ( data_buffer case CMD_WR_BLOCK:
, data_counter data_counter = ( cmd_buffer[7] << 8 ) | cmd_buffer[6];
);
errorcode = 1;
if ( data_counter == WDC_BLOCKLEN ) {
errorcode = wdc_write_sector ( blockno, data_buffer );
} else {
errorcode = wdc_write_multiblock ( blockno, data_buffer, data_counter / WDC_BLOCKLEN );
}
if ( errorcode ) blockno = wdc_p8kblock2sdblock ( ( ( uint32_t ) cmd_buffer[5] << 24 ) | ( ( uint32_t ) cmd_buffer[4] << 16 ) | ( ( uint16_t ) cmd_buffer[3] << 8 ) | cmd_buffer[2] );
wdc_send_error(); wdc_receive_data ( data_buffer
break; , data_counter
);
errorcode = 1;
if ( data_counter == WDC_BLOCKLEN ) {
errorcode = wdc_write_sector ( blockno, data_buffer );
} else {
errorcode = wdc_write_multiblock ( blockno, data_buffer, data_counter / WDC_BLOCKLEN );
}
case CMD_RD_BLOCK: if ( errorcode )
data_counter = ( cmd_buffer[7] << 8 ) | cmd_buffer[6]; wdc_send_error();
break;
blockno = wdc_p8kblock2sdblock ( ( ( uint32_t ) cmd_buffer[5] << 24 ) | ( ( uint32_t ) cmd_buffer[4] << 16 ) | ( ( uint16_t ) cmd_buffer[3] << 8 ) | cmd_buffer[2] ); case CMD_RD_BLOCK:
data_counter = ( cmd_buffer[7] << 8 ) | cmd_buffer[6];
errorcode = 1; blockno = wdc_p8kblock2sdblock ( ( ( uint32_t ) cmd_buffer[5] << 24 ) | ( ( uint32_t ) cmd_buffer[4] << 16 ) | ( ( uint16_t ) cmd_buffer[3] << 8 ) | cmd_buffer[2] );
if ( data_counter == WDC_BLOCKLEN ) {
errorcode = wdc_read_sector ( blockno, data_buffer ); errorcode = 1;
} else { if ( data_counter == WDC_BLOCKLEN ) {
errorcode = wdc_read_multiblock ( blockno, data_buffer, data_counter / WDC_BLOCKLEN ); errorcode = wdc_read_sector ( blockno, data_buffer );
} } else {
errorcode = wdc_read_multiblock ( blockno, data_buffer, data_counter / WDC_BLOCKLEN );
}
if ( errorcode ) {
wdc_send_error();
} else {
wdc_send_data ( data_buffer
, data_counter
);
}
break;
case CMD_WR_WDC_RAM:
data_counter = ( cmd_buffer[7] << 8 ) | cmd_buffer[6];
wdc_receive_data ( data_buffer
, data_counter
);
wdc_write_data_to_ram ( data_buffer
, convert_ram_address ( ( cmd_buffer[2] << 8 ) | cmd_buffer[1] )
, data_counter
);
break;
case CMD_RD_WDC_RAM:
data_counter = ( cmd_buffer[7] << 8 ) | cmd_buffer[6];
wdc_read_data_from_ram ( data_buffer
, convert_ram_address ( ( cmd_buffer[2] << 8 ) | cmd_buffer[1] )
, data_counter
);
if ( errorcode ) {
wdc_send_error();
} else {
wdc_send_data ( data_buffer wdc_send_data ( data_buffer
, data_counter , data_counter
); );
} break;
break;
case CMD_WR_WDC_RAM: case CMD_RD_PARTAB:
data_counter = ( cmd_buffer[7] << 8 ) | cmd_buffer[6]; data_counter = ( cmd_buffer[7] << 8 ) | cmd_buffer[6];
wdc_receive_data ( data_buffer wdc_read_par_table ( data_buffer
, data_counter , data_counter );
);
wdc_write_data_to_ram ( data_buffer wdc_send_data ( data_buffer
, convert_ram_address ( ( cmd_buffer[2] << 8 ) | cmd_buffer[1] ) , data_counter
, data_counter );
); break;
break;
case CMD_RD_WDC_RAM: case CMD_WR_PARTAB:
data_counter = ( cmd_buffer[7] << 8 ) | cmd_buffer[6]; data_counter = ( cmd_buffer[7] << 8 ) | cmd_buffer[6];
wdc_read_data_from_ram ( data_buffer wdc_receive_data ( data_buffer
, convert_ram_address ( ( cmd_buffer[2] << 8 ) | cmd_buffer[1] ) , data_counter
, data_counter );
);
wdc_send_data ( data_buffer wdc_write_wdc_par ( data_buffer
, data_counter , data_counter );
);
break;
case CMD_RD_PARTAB: break;
data_counter = ( cmd_buffer[7] << 8 ) | cmd_buffer[6];
wdc_read_par_table ( data_buffer case CMD_DL_BTTAB:
, data_counter ); wdc_del_wdc_btt();
break;
wdc_send_data ( data_buffer case CMD_RD_BTTAB:
, data_counter data_counter = ( cmd_buffer[7] << 8 ) | cmd_buffer[6];
);
break;
case CMD_WR_PARTAB: wdc_read_wdc_btt ( data_buffer
data_counter = ( cmd_buffer[7] << 8 ) | cmd_buffer[6]; , data_counter );
wdc_receive_data ( data_buffer wdc_send_data ( data_buffer
, data_counter , data_counter
); );
break;
wdc_write_wdc_par ( data_buffer case CMD_WR_BTTAB:
, data_counter ); data_counter = ( cmd_buffer[7] << 8 ) | cmd_buffer[6];
break;
case CMD_DL_BTTAB: wdc_receive_data ( data_buffer
wdc_del_wdc_btt(); , data_counter
break; );
case CMD_RD_BTTAB: wdc_write_wdc_btt ( data_buffer
data_counter = ( cmd_buffer[7] << 8 ) | cmd_buffer[6]; , data_counter );
break;
wdc_read_wdc_btt ( data_buffer case CMD_FMTRD_TRACK:
, data_counter ); case CMD_FMTBTT_TRACK:
wdc_send_data ( data_buffer /* no cylinder 0 formatting if command is CMD_FMTBTT_TRACK */
, data_counter if ( cmd_buffer[0] == CMD_FMTBTT_TRACK && ( cmd_buffer[2] | ( cmd_buffer[3] << 8 ) ) == 0 )
); break;
break;
case CMD_WR_BTTAB: data_counter = WDC_BLOCKLEN;
data_counter = ( cmd_buffer[7] << 8 ) | cmd_buffer[6];
wdc_receive_data ( data_buffer memset ( &data_buffer[0], 0x00, data_counter );
, data_counter blockno = wdc_sector2sdblock ( cmd_buffer[2] | ( cmd_buffer[3] << 8 )
); , cmd_buffer[4]
, cmd_buffer[5]
);
wdc_write_wdc_btt ( data_buffer errorcode = 1;
, data_counter ); for ( i8 = 0; i8 < wdc_get_hdd_sectors(); i8++ ) {
break; errorcode = wdc_write_sector ( blockno, data_buffer );
if ( errorcode ) break;
case CMD_FMTBTT_TRACK: blockno++;
data_counter = WDC_BLOCKLEN;
memset ( &data_buffer[0], 0x00, data_counter );
blockno = wdc_sector2sdblock ( 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 {
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
);
} }
}
break;
case CMD_ST_PARBTT:
data_counter = WDC_BLOCKLEN;
blockno = 0; if ( errorcode ) {
wdc_read_par_table ( data_buffer if ( cmd_buffer[0] == CMD_FMTRD_TRACK ) {
, data_counter ); wdc_send_error();
} else {
if ( wdc_add_btt_entry ( cmd_buffer[2] | ( cmd_buffer[3] << 8 ), cmd_buffer[4] ) ) {
wdc_send_error();
} else {
data_buffer[0] = cmd_buffer[2]; /* Track Low */
data_buffer[1] = cmd_buffer[3]; /* Track High */
data_buffer[2] = cmd_buffer[4]; /* Head */
errorcode = wdc_write_sector ( blockno, data_buffer ); wdc_send_data ( data_buffer
if ( errorcode ) , 3
wdc_send_error(); );
break; }
}
}
break;
case CMD_RD_WDCERR: case CMD_ST_PARBTT:
data_counter = ( cmd_buffer[7] << 8 ) | cmd_buffer[6]; data_counter = WDC_BLOCKLEN;
memset ( &data_buffer[0], 0x00, data_counter ); blockno = 0;
wdc_send_data ( data_buffer wdc_set_disk_valid();
, data_counter wdc_read_par_table ( data_buffer
); , data_counter );
break;
case CMD_VER_TRACK:
data_counter = WDC_BLOCKLEN;
blockno = wdc_sector2sdblock ( 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();
break;
case CMD_RD_SECTOR:
data_counter = ( cmd_buffer[7] << 8 ) | cmd_buffer[6];
blockno = wdc_sector2sdblock ( cmd_buffer[2] | ( cmd_buffer[3] << 8 )
, cmd_buffer[4]
, cmd_buffer[5]
);
errorcode = 1;
if ( data_counter == WDC_BLOCKLEN ) {
errorcode = wdc_write_sector ( blockno, data_buffer ); errorcode = wdc_write_sector ( blockno, data_buffer );
} else { if ( errorcode )
errorcode = wdc_write_multiblock ( blockno, data_buffer, data_counter / WDC_BLOCKLEN ); wdc_send_error();
}
if ( errorcode ) break;
wdc_send_error();
break;
default: case CMD_RD_WDCERR:
data_counter = ( cmd_buffer[7] << 8 ) | cmd_buffer[6];
memset ( &data_buffer[0], 0x00, data_counter );
wdc_send_data ( data_buffer
, data_counter
);
break;
case CMD_VER_TRACK:
data_counter = WDC_BLOCKLEN;
blockno = wdc_sector2sdblock ( 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();
break;
case CMD_RD_SECTOR:
data_counter = ( cmd_buffer[7] << 8 ) | cmd_buffer[6];
blockno = wdc_sector2sdblock ( cmd_buffer[2] | ( cmd_buffer[3] << 8 )
, cmd_buffer[4]
, cmd_buffer[5]
);
errorcode = 1;
if ( data_counter == WDC_BLOCKLEN ) {
errorcode = wdc_write_sector ( blockno, data_buffer );
} else {
errorcode = wdc_write_multiblock ( blockno, data_buffer, data_counter / WDC_BLOCKLEN );
}
if ( errorcode )
wdc_send_error();
break;
default:
#if DEBUG >= 1 #if DEBUG >= 1
uart_puts_p ( PSTR ( " Unknown command:" ) ); uart_puts_p ( PSTR ( " Unknown command:" ) );
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] );
uart_putc_hex ( cmd_buffer[3] ); uart_putc_hex ( cmd_buffer[3] );
uart_putc_hex ( cmd_buffer[4] ); uart_putc_hex ( cmd_buffer[4] );
uart_putc_hex ( cmd_buffer[5] ); uart_putc_hex ( cmd_buffer[5] );
uart_putc_hex ( cmd_buffer[6] ); uart_putc_hex ( cmd_buffer[6] );
uart_putc_hex ( cmd_buffer[7] ); uart_putc_hex ( cmd_buffer[7] );
uart_putc_hex ( cmd_buffer[8] ); uart_putc_hex ( cmd_buffer[8] );
uart_putc ( '\n' ); uart_putc ( '\n' );
#endif #endif
wdc_send_error(); wdc_send_error();
break; break;
}
} }
} }
#endif #endif
@ -361,10 +405,8 @@ void atmega_setup ( void )
set_sleep_mode ( SLEEP_MODE_IDLE ); set_sleep_mode ( SLEEP_MODE_IDLE );
uart_init(); uart_init();
wdc_init_ports(); wdc_init_ports();
while ( wdc_init_sdcard() ) { if ( wdc_init_sdcard() ) {
#if DEBUG >= 1 wdc_set_no_disk();
uart_puts_p ( PSTR ( "SDCard initialisation failed!" ) );
#endif
} }
} }

View File

@ -26,7 +26,7 @@
*/ */
/* /*
* $Id: wdc_main.h,v 1.10 2012/06/07 18:01:02 olivleh1 Exp $ * $Id: wdc_main.h,v 1.11 2012/06/09 00:22:28 olivleh1 Exp $
*/ */
@ -39,7 +39,7 @@
#define CMD_RD_WDC_RAM 0x08 /* read data from WDC RAM */ #define CMD_RD_WDC_RAM 0x08 /* read data from WDC RAM */
#define ___CMD_RDBTT_SECTOR 0x11 /* read sector taking BTT into account */ #define ___CMD_RDBTT_SECTOR 0x11 /* read sector taking BTT into account */
#define ___CMD_WRBTT_SECTOR 0x12 /* write sector taking BTT into account */ #define ___CMD_WRBTT_SECTOR 0x12 /* write sector taking BTT into account */
#define ___CMD_FMTRD_TRACK 0x14 /* format and reread a track */ #define CMD_FMTRD_TRACK 0x14 /* format and reread a track */
#define CMD_WR_WDC_RAM 0x18 /* write data to WDC RAM */ #define CMD_WR_WDC_RAM 0x18 /* write data to WDC RAM */
#define CMD_RD_BLOCK 0x21 /* read data beginning at given block */ #define CMD_RD_BLOCK 0x21 /* read data beginning at given block */
#define CMD_WR_BLOCK 0x22 /* write data beginning at given block */ #define CMD_WR_BLOCK 0x22 /* write data beginning at given block */

View File

@ -26,19 +26,78 @@
*/ */
/* /*
* $Id: wdc_par.c,v 1.2 2012/06/07 18:01:02 olivleh1 Exp $ * $Id: wdc_par.c,v 1.3 2012/06/09 00:22:28 olivleh1 Exp $
*/ */
#include <avr/pgmspace.h> #include <avr/pgmspace.h>
#include "wdc_par.h" #include "wdc_par.h"
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, * unformatted ST138
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 * 57 44 43 5F 34 2E 32 81 81 81 81 81 81 81 81 81
}; * 81 81 81 81 81 81 81 64 00 02 12 64 00 01 81 81
* 81 81 81 81 81 81 81 81 81 81 EB 0D 00 00 41 00
* 01 01 81 81 81 81 81 81 81 81 81 81 81 81 81 81
* 81 81 81 81 81 EB 0D 00 00 24 00 00 81 81 81 81
* 00 81 00 80 FE 00 00 00 01 81 81 73 00 12 81 01
* 00 02 00 00 81 81 81 00 41 D7 28 81 81 81 81 81
* 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81
*
*
* fresh formatted ST138
*
* 57 44 43 5F 34 2E 32 81 53 54 32 35 31 2D 31 20
* 20 20 20 20 81 00 00 34 03 06 12 34 03 01 00 00
* 00 00 00 00 CB D1 FB FD F1 F3 83 59 01 00 01 09
* 00 01 81 81 81 81 81 81 81 81 81 81 81 81 81 81
* 81 81 81 81 81 83 59 01 00 6C 00 00 81 81 81 E5
* 00 81 00 80 FE 00 00 00 01 81 81 33 00 12 81 00
* 00 00 00 00 81 81 81 09 01 D7 28 81 81 81 81 81
* 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81
*
*
* no harddrive attached:
*
* 57 44 43 5F 34 2E 32 81 81 81 81 81 81 81 81 81
* 81 81 81 81 81 81 81 64 00 02 12 64 00 01 81 81
* 81 81 81 81 81 81 81 81 81 81 81 81 81 81 40 00
* 00 00 81 81 81 81 81 81 81 81 81 81 81 81 81 81
* 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81
* 00 81 00 80 81 81 81 81 81 81 81 33 00 12 81 00
* 81 81 81 81 81 81 81 00 40 D7 81 81 81 81 81 81
* 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81 81
*
*/
uint8_t par_table[512];
const uint8_t
par_tab_new_dsk[128] = {'W', 'D', 'C', '_', '4', '.', '2', 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x64, 0x00, 0x02, 0x12, 0x64, 0x00, 0x01, 0x81, 0x81,
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, /* init with sa.format ends here */
/* to be initiated by controller starts here */ 0xEB, 0x0D, 0x00, 0x00, 0x41, 0x00,
0x01, 0x01, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
0x81, 0x81, 0x81, 0x81, 0x81, 0xEB, 0x0D, 0x00, 0x00, 0x24, 0x00, 0x00, 0x81, 0x81, 0x81, 0x81,
0x00, 0x81, 0x00, 0x80, 0xfe, 0x00, 0x00, 0x00, 0x01, 0x81, 0x81, 0x73, 0x00, 0x12, 0x81, 0x01,
0x00, 0x02, 0x00, 0x00, 0x81, 0x81, 0x81, 0x00, 0x41, 0xd7, 0x28, 0x81, 0x81, 0x81, 0x81, 0x81,
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
};
const uint8_t
par_tab_no_dsk[128] = {'W', 'D', 'C', '_', '4', '.', '2', 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x64, 0x00, 0x02, 0x12, 0x64, 0x00, 0x01, 0x81, 0x81,
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, /* init with sa.format ends here */
/* to be initiated by controller starts here */ 0x81, 0x81, 0x81, 0x81, 0x40, 0x00,
0x00, 0x00, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
0x00, 0x81, 0x00, 0x80, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x33, 0x00, 0x12, 0x81, 0x00,
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x00, 0x40, 0xd7, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
};
uint8_t valid_disk = 1;
void wdc_read_par_table ( uint8_t *buffer, uint16_t count ) void wdc_read_par_table ( uint8_t *buffer, uint16_t count )
{ {
do { do {
@ -136,3 +195,60 @@ uint8_t wdc_get_hdd_heads()
{ {
return ( par_table[17 + POS_PAR_WDC_PAR] ); return ( par_table[17 + POS_PAR_WDC_PAR] );
} }
uint16_t wdc_get_hdd_cylinder()
{
return ( ( par_table[16 + POS_PAR_WDC_PAR] << 8 ) | par_table[15 + POS_PAR_WDC_PAR] );
}
void wdc_set_disk_invalid()
{
valid_disk = 0;
uint8_t i;
for ( i = 0; i < 128; i++ )
par_table[i] = par_tab_new_dsk[i];
}
void wdc_set_disk_valid()
{
uint32_t blocks;
uint16_t zw0, zw1;
blocks = (uint32_t)wdc_get_hdd_sectors() * (uint32_t)wdc_get_hdd_heads() * (uint32_t) wdc_get_hdd_cylinder()
- (uint32_t)wdc_get_hdd_sectors() * (uint32_t)wdc_get_hdd_heads();
zw0 = blocks / 65536;
zw1 = ( blocks % 65536 ) - 1;
valid_disk = 1;
par_table[42] = zw1;
par_table[43] = zw1 >> 8;
par_table[44] = zw0;
par_table[45] = zw0 >> 8;
par_table[46] = 0x01;
par_table[47] = 0x09;
par_table[48] = 0x00;
par_table[69] = 0x83;
par_table[70] = 0x59;
par_table[71] = 0x01;
par_table[73] = 0x6c;
par_table[91] = 0x33;
par_table[95] = 0x00;
}
void wdc_set_no_disk()
{
uint8_t i;
valid_disk = 0;
for ( i = 0; i < 128; i++ )
par_table[i] = par_tab_no_dsk[i];
}
uint8_t wdc_get_disk_valid()
{
return valid_disk;
}
uint8_t wdc_get_num_of_drvs()
{
return par_table[49];
}

View File

@ -26,7 +26,7 @@
*/ */
/* /*
* $Id: wdc_par.h,v 1.2 2012/06/07 18:01:02 olivleh1 Exp $ * $Id: wdc_par.h,v 1.3 2012/06/09 00:22:29 olivleh1 Exp $
*/ */
#ifndef WDC_PAR_H_ #ifndef WDC_PAR_H_
@ -47,12 +47,19 @@ extern uint8_t wdc_add_btt_entry ( uint16_t cylinder, uint8_t head );
extern uint8_t wdc_get_hdd_sectors(); extern uint8_t wdc_get_hdd_sectors();
extern uint8_t wdc_get_hdd_heads(); extern uint8_t wdc_get_hdd_heads();
void wdc_set_disk_invalid();
void wdc_set_disk_valid();
uint8_t wdc_get_disk_valid();
void wdc_set_no_disk();
uint8_t wdc_get_num_of_drvs();
#define POS_PAR_VERSION 0 #define POS_PAR_VERSION 0
#define POS_PAR_WDC_PAR 8 #define POS_PAR_WDC_PAR 8
#define POS_PAR_WDC_BTT 88 #define POS_PAR_WDC_BTT 0x88
#define SIZE_PAR_VERSION 8 #define SIZE_PAR_VERSION 8
#define SIZE_PAR_WDC_PAR 80 #define SIZE_PAR_WDC_PAR 0x80
#define SIZE_PAR_WDC_BTT 125 #define SIZE_PAR_WDC_BTT 125
#endif /* WDC_PAR_H_ */ #endif /* WDC_PAR_H_ */