diff --git a/P8000_WDC_Emulator/P8000_WDC_Emulator/Hardware/P8000_WDC_Emulator.sch b/P8000_WDC_Emulator/P8000_WDC_Emulator/Hardware/P8000_WDC_Emulator.sch index da2f5c9..6626932 100755 --- a/P8000_WDC_Emulator/P8000_WDC_Emulator/Hardware/P8000_WDC_Emulator.sch +++ b/P8000_WDC_Emulator/P8000_WDC_Emulator/Hardware/P8000_WDC_Emulator.sch @@ -174,7 +174,7 @@ T 67100 33100 9 8 1 0 0 0 1 T 68500 33100 9 8 1 0 0 0 1 1 T 71000 33400 9 7 1 0 0 0 1 -$Revision: 1.14 $ / $Date: 2012/06/13 20:17:45 $ +$Revision: 1.15 $ / $Date: 2012/06/15 22:42:42 $ T 71000 33100 9 8 1 0 0 0 1 Oliver Lehmann N 50600 59400 51200 59400 4 @@ -427,7 +427,7 @@ C 68600 50100 1 90 0 resistor-1.sym T 68200 50400 5 10 0 0 90 0 1 device=RESISTOR T 68700 50600 5 10 1 1 0 0 1 -refdes=R5 +refdes=1R5 T 68700 50400 5 10 1 1 0 0 1 value=330 } @@ -941,14 +941,14 @@ C 45100 50300 1 0 1 busripper-1.sym T 45100 50700 5 8 0 0 0 6 1 device=none T 45200 50400 5 10 1 1 0 0 1 -pinlabel=DA2 +pinlabel=DA1 } C 45100 50000 1 0 1 busripper-1.sym { T 45100 50400 5 8 0 0 0 6 1 device=none T 45200 50100 5 10 1 1 0 0 1 -pinlabel=DA1 +pinlabel=DA2 } C 45100 56300 1 0 1 busripper-1.sym { @@ -983,7 +983,7 @@ C 31300 39900 1 0 0 switch-dip4-1.sym T 32700 41275 5 8 0 0 0 0 1 device=SWITCH_DIP4 T 31600 41450 5 10 1 1 0 0 1 -refdes=U? +refdes=SW1 } C 37300 38400 1 0 1 74245-1.sym { @@ -1000,7 +1000,7 @@ C 33900 38900 1 180 0 resistorpack5-1.sym T 33800 37500 5 10 0 0 180 0 1 device=RESISTORPACK_5 T 33800 37700 5 10 1 1 180 0 1 -refdes=R7 +refdes=R6 T 34000 38100 5 10 1 1 0 0 1 netname=4k7 } @@ -1255,7 +1255,7 @@ C 71200 38700 1 270 1 resistor-1.sym T 71600 39000 5 10 0 0 270 6 1 device=RESISTOR T 71100 39300 5 10 1 1 90 6 1 -refdes=R6 +refdes=2R5 T 71600 39300 5 10 1 1 90 6 1 value=330 } @@ -1847,7 +1847,7 @@ pinlabel=\_RESET\_ } N 51200 61700 55000 61700 4 N 55000 46900 55000 61700 4 -N 55000 46900 67000 46900 4 +N 55000 46900 70500 46900 4 N 67000 46900 67000 46000 4 C 35300 39800 1 90 0 5V-plus-1.sym C 35300 39500 1 90 0 5V-plus-1.sym @@ -1917,18 +1917,6 @@ device=none T 38300 39200 5 10 1 1 0 0 1 pinlabel=PA7 } -N 70500 40400 70500 42000 4 -N 70500 42900 70500 43400 4 -C 70300 43400 1 0 0 5V-plus-1.sym -C 70600 42000 1 90 0 resistor-1.sym -{ -T 70200 42300 5 10 0 0 90 0 1 -device=RESISTOR -T 70300 42200 5 10 1 1 90 0 1 -refdes=2R3 -T 70800 42200 5 10 1 1 90 0 1 -value=10k -} N 52300 45500 52300 41500 4 C 37600 60100 1 0 1 7403-1.sym { @@ -1976,3 +1964,4 @@ T 40300 60300 5 10 0 0 0 6 1 slot=2 } N 37600 60800 39200 60800 4 +N 70500 46900 70500 40400 4 diff --git a/P8000_WDC_Emulator/P8000_WDC_Emulator/wdc_drv_pata.c b/P8000_WDC_Emulator/P8000_WDC_Emulator/wdc_drv_pata.c index 43de991..fe949e7 100644 --- a/P8000_WDC_Emulator/P8000_WDC_Emulator/wdc_drv_pata.c +++ b/P8000_WDC_Emulator/P8000_WDC_Emulator/wdc_drv_pata.c @@ -26,7 +26,7 @@ */ /* - * $Id: wdc_drv_pata.c,v 1.3 2012/06/14 20:24:24 olivleh1 Exp $ + * $Id: wdc_drv_pata.c,v 1.4 2012/06/15 22:42:42 olivleh1 Exp $ */ #include "wdc_config.h" @@ -34,6 +34,15 @@ #include #include "wdc_avr.h" #include "uart.h" +#include "wdc_drv_pata.h" + +uint8_t pata_bsy(); +uint8_t pata_rdy(); +uint8_t pata_drq(); +void pata_cmd ( uint8_t cmd ); +void ata_identify(); + +#define ata_ctl_high() ata_cs0_disable();ata_cs1_disable();ata_da0_disable();ata_da1_disable();ata_da2_disable(); void pata_set_highbyte ( uint8_t byte ) { @@ -41,7 +50,7 @@ void pata_set_highbyte ( uint8_t byte ) enable_atalatch(); nop(); nop(); - disable_atalatch(); + init_addressdecoder(); } void pata_set_lowbyte ( uint8_t byte ) @@ -52,23 +61,377 @@ void pata_set_lowbyte ( uint8_t byte ) void pata_send_data() { enable_rdwrtoata(); - _delay_us(10); -// disable_rdwrtoata(); + _delay_us ( 10 ); + init_addressdecoder(); +} + + +uint8_t pata_get_lowbyte () +{ + nop(); + nop(); + return port_data_get(); +} + +uint8_t pata_get_highbyte () +{ + uint8_t byte; + enable_atalatch(); + nop(); + nop(); + nop(); + byte = port_data_get(); + init_addressdecoder(); + return byte; +} + +uint8_t pata_read_byte() +{ + uint8_t byte; + + configure_port_data_read(); + ata_rd_enable(); + enable_rdwrtoata(); + _delay_us ( 1 ); + byte = pata_get_lowbyte(); + init_addressdecoder(); + ata_rd_disable(); + + return byte; +} + +void pata_write_byte ( uint8_t byte ) +{ + configure_port_data_write(); + pata_set_lowbyte ( byte ); + enable_rdwrtoata(); + ata_wr_enable(); + _delay_us ( 1 ); + ata_wr_disable(); + init_addressdecoder(); + +} + + +uint8_t ata_get_status_byte ( void ) +{ + uint8_t byte; + ata_cs0_enable(); + byte = pata_read_byte(); + ata_ctl_high(); + + return byte; +} + +uint8_t ata_get_alt_status_byte ( void ) +{ + uint8_t byte; + ata_cs1_enable(); + ata_da0_enable(); + byte = pata_read_byte(); + ata_ctl_high(); + + return byte; +} + + +uint16_t pata_read_word ( uint8_t ofs, uint8_t count ) +{ + uint16_t word; + uint8_t byte_l; + uint8_t byte_h; + uint8_t c = 0; + + ata_da0_enable(); + ata_da1_enable(); + ata_da2_enable(); + ata_cs0_enable(); + + do { + + ata_rd_enable(); + enable_rdwrtoata(); + nop(); + nop(); + nop(); + byte_l = port_data_get(); + disable_rdwrtoata(); + enable_atalatch(); + nop(); + nop(); + nop(); + byte_h = port_data_get(); + disable_atalatch(); + ata_rd_disable(); + + if ( count && ( c >= ofs ) ) { + uart_putc ( byte_h ); + uart_putc ( byte_l ); + count--; + } + } while ( ++c ); + + ata_ctl_high(); + + word = byte_h << 8; + word |= byte_l; + + return ( word ); +} + + +uint16_t pata_read_single_word () +{ + uint16_t word; + uint8_t byte_l; + uint8_t byte_h; + + ata_da0_enable(); + ata_da1_enable(); + ata_da2_enable(); + ata_cs0_enable(); + + ata_rd_enable(); + enable_rdwrtoata(); + nop(); + nop(); + nop(); + byte_l = port_data_get(); + disable_rdwrtoata(); + enable_atalatch(); + nop(); + nop(); + nop(); + byte_h = port_data_get(); + disable_atalatch(); + ata_rd_disable(); + + ata_ctl_high(); + + word = byte_h << 8; + word |= byte_l; + + return ( word ); } uint8_t pata_init () { -uart_putc('1'); - /* test write */ - configure_port_data_write(); - ata_wr_enable(); - pata_set_highbyte ( 0xff ); - pata_set_lowbyte ( 0x00 ); - pata_send_data(); -// ata_wr_disable(); + + // is needed for some disks (for example Maxtor 6L080J4) + _delay_ms ( 100 ); + + uart_puts_p ( PSTR ( "Init start\n" ) ); + + while ( ( !pata_rdy() ) & pata_bsy() ); + + uart_putc_hex ( ata_get_status_byte() ); + + /*device register*/ + ata_da0_enable(); + ata_cs0_enable(); +#ifdef PIO + pata_write_byte ( 0 ); // Drive 0, PIO +#else + pata_write_byte ( 0xE0 ); // Drive 0, LBA +#endif + ata_ctl_high(); + +#ifdef PIO + while ( pata_bsy() ); + + //device control + ata_da0_enable(); + ata_cs1_enable(); + pata_write_byte ( 0x40 | 0x20 ); // reset + no interrupt + ata_ctl_high(); + + _delay_ms ( 20 ); + + ata_da0_enable(); + ata_cs1_enable(); + pata_write_byte ( 0x20 ); // no interrupt + ata_ctl_high(); + + _delay_ms ( 20 ); + + while ( ( !pata_rdy() ) & pata_bsy() ); + + //feature register + ata_da1_enable(); + ata_da2_enable(); + ata_cs0_enable(); + pata_write_byte ( 3 ); // PIO + ata_ctl_high(); + + //sector count + ata_da0_enable(); + ata_da2_enable(); + ata_cs0_enable(); + pata_write_byte ( 1 ); + ata_ctl_high(); + + //command + ata_cs0_enable(); + pata_write_byte ( 0xEF ); // Set Features + ata_ctl_high(); +#else + + while ( ( !pata_rdy() ) & pata_bsy() ); + /*command*/ + ata_cs0_enable(); + pata_write_byte ( 0x10 ); // Recalibrate + ata_ctl_high(); +#endif + while ( pata_bsy() ); + + uart_puts_p ( PSTR ( "disk is now ready\n" ) ); + + ata_identify(); + return 1; } + +void ata_identify() +{ + uint32_t dword; + uint16_t word; + uint8_t byte_l,byte_h; + + /*command*/ + while ( pata_bsy() ); + ata_cs0_enable(); + pata_write_byte ( 0xEc ); // Identify + ata_ctl_high(); + + /* Wait for BSY goes low and DRQ goes high */ + while ( ( ata_get_status_byte() & ( ATA_STAT_BSY | ATA_STAT_DRQ ) ) != ATA_STAT_DRQ ); + + word = pata_read_single_word(); // General configuration bit + word = pata_read_single_word(); + uart_puts_p ( PSTR ( "Number of logical cylinders: " ) ); + uart_putw_dec(word); + uart_putc('\n'); + word = pata_read_single_word(); // Specific configuration + word = pata_read_single_word(); + uart_puts_p ( PSTR ( "Number of logical heads: " ) ); + uart_putw_dec(word); + uart_putc('\n'); + word = pata_read_single_word(); + word = pata_read_single_word(); + word = pata_read_single_word(); + uart_puts_p ( PSTR ( "Number of logical sectors per logical track: " ) ); + uart_putw_dec(word); + uart_putc('\n'); + word = pata_read_single_word(); // CompactFlash + word = pata_read_single_word(); // CompactFlash + word = pata_read_single_word(); // Retired + uart_puts_p ( PSTR ( "Serial number: " ) ); + for(uint8_t i=0;i<10;i++) { + word = pata_read_single_word(); + byte_h = word >> 8; + byte_l = word & 0x00FF; + uart_putc(byte_h); + uart_putc(byte_l); + } + uart_putc('\n'); + word = pata_read_single_word(); // Retired + word = pata_read_single_word(); // Retired + word = pata_read_single_word(); // Obsolete + uart_puts_p ( PSTR ( "Firmware revision: " ) ); + for(uint8_t i=0;i<4;i++) { + word = pata_read_single_word(); + byte_h = word >> 8; + byte_l = word & 0x00FF; + uart_putc(byte_h); + uart_putc(byte_l); + } + uart_putc('\n'); + uart_puts_p ( PSTR ( "Model number: " ) ); + for(uint8_t i=0;i<20;i++) { + word = pata_read_single_word(); + byte_h = word >> 8; + byte_l = word & 0x00FF; + uart_putc(byte_h); + uart_putc(byte_l); + } + uart_putc('\n'); + word = pata_read_single_word(); // no idea + word = pata_read_single_word(); // Reserved + word = pata_read_single_word(); // Capabilities + word = pata_read_single_word(); // Capabilities + word = pata_read_single_word(); // Obsolete + word = pata_read_single_word(); // Obsolete + word = pata_read_single_word(); // Reserved + word = pata_read_single_word(); + uart_puts_p ( PSTR ( "Number of current logical cylinders: " ) ); + uart_putw_dec(word); + uart_putc('\n'); + word = pata_read_single_word(); + uart_puts_p ( PSTR ( "Number of current logical heads: " ) ); + uart_putw_dec(word); + uart_putc('\n'); + word = pata_read_single_word(); + uart_puts_p ( PSTR ( "Number of current logical sectors per track: " ) ); + uart_putw_dec(word); + uart_putc('\n'); + word = pata_read_single_word(); + dword = word; + word = pata_read_single_word(); + dword |= (uint32_t)word<<16; + uart_puts_p ( PSTR ( "Current capacity in sectors: " ) ); + uart_putdw_dec(dword); + uart_putc('\n'); + word = pata_read_single_word(); // Reserved + word = pata_read_single_word(); + dword = word; + word = pata_read_single_word(); + dword |= (uint32_t)word <<16; + uart_puts_p ( PSTR ( "Total number of user addressable sectors (LBA mode only): " ) ); + uart_putdw_dec(dword); + uart_putc('\n'); + word = pata_read_single_word(); // Obsolete + for(uint8_t i=0;i<193;i++) + word = pata_read_single_word(); // ignore it +} + +uint8_t pata_rdy() +{ + uint8_t i; + if ( ata_get_status_byte() & ATA_STAT_RDY ) + i = 1; + else + i = 0; + return i; +} + +uint8_t pata_bsy() +{ + uint8_t i; + if ( ata_get_status_byte() & ATA_STAT_BSY ) + i = 1; + else + i = 0; + return i; +} + +uint8_t pata_drq() +{ + uint8_t i; + if ( ata_get_status_byte() & ATA_STAT_DRQ ) + i = 1; + else + i = 0; + return i; +} + +void pata_cmd ( uint8_t cmd ) +{ + ata_cs0_enable(); + pata_write_byte ( cmd ); + ata_ctl_high(); +} + uint8_t pata_read_block ( uint32_t addr, uint8_t *buffer ) { return 1; diff --git a/P8000_WDC_Emulator/P8000_WDC_Emulator/wdc_drv_pata.h b/P8000_WDC_Emulator/P8000_WDC_Emulator/wdc_drv_pata.h index deee335..84b39cb 100644 --- a/P8000_WDC_Emulator/P8000_WDC_Emulator/wdc_drv_pata.h +++ b/P8000_WDC_Emulator/P8000_WDC_Emulator/wdc_drv_pata.h @@ -26,16 +26,12 @@ */ /* - * $Id: wdc_drv_pata.h,v 1.3 2012/06/14 20:24:24 olivleh1 Exp $ + * $Id: wdc_drv_pata.h,v 1.4 2012/06/15 22:42:42 olivleh1 Exp $ */ #ifndef WDC_DRV_PATA_H_ #define WDC_DRV_PATA_H_ -extern void pata_set_highbyte(uint8_t byte); -extern void pata_set_lowbyte(uint8_t byte); -extern void pata_send_data(); - extern uint8_t pata_init (); extern uint8_t pata_read_block ( uint32_t addr, uint8_t *buffer ); @@ -44,4 +40,67 @@ extern uint8_t pata_write_block ( uint32_t addr, uint8_t *buffer ); extern uint8_t pata_read_multiblock ( uint32_t addr, uint8_t *buffer, uint8_t numblocks ); extern uint8_t pata_write_multiblock ( uint32_t addr, uint8_t *buffer, uint8_t numblocks ); + +#define ATA_STAT_BSY 0x80 // ATA busy +#define ATA_STAT_RDY 0x40 // ATA ready +#define ATA_STAT_DF 0x20 // ATA device fault +#define ATA_STAT_SKC 0x10 // ATA seek complete +#define ATA_STAT_DRQ 0x08 // ATA data request +#define ATA_STAT_CORR 0x04 // ATA corrected +#define ATA_STAT_IDX 0x02 // ATA index +#define ATA_STAT_ERR 0x01 // ATA error + +#define ATA_DH_DEV0 0xE0 +#define ATA_DH_DEV1 0xF0 + +//ATA commands (from ATA-3), +#define CMD_CFA_ERASE_SECTORS 0xC0 +#define CMD_CFA_REQUEST_EXT_ERR_CODE 0x03 +#define CMD_CFA_TRANSLATE_SECTOR 0x87 +#define CMD_CFA_WRITE_MULTIPLE_WO_ERASE 0xCD +#define CMD_CFA_WRITE_SECTORS_WO_ERASE 0x38 +#define CMD_CHECK_POWER_MODE1 0xE5 +#define CMD_CHECK_POWER_MODE2 0x98 +#define CMD_DEVICE_RESET 0x08 +#define CMD_EXECUTE_DEVICE_DIAGNOSTIC 0x90 +#define CMD_FLUSH_CACHE 0xE7 +#define CMD_FORMAT_TRACK 0x50 +#define CMD_IDENTIFY_DEVICE 0xEC +#define CMD_IDENTIFY_DEVICE_PACKET 0xA1 +#define CMD_IDENTIFY_PACKET_DEVICE 0xA1 +#define CMD_IDLE1 0xE3 +#define CMD_IDLE2 0x97 +#define CMD_IDLE_IMMEDIATE1 0xE1 +#define CMD_IDLE_IMMEDIATE2 0x95 +#define CMD_INITIALIZE_DRIVE_PARAMETERS 0x91 +#define CMD_INITIALIZE_DEVICE_PARAMETERS 0x91 +#define CMD_NOP 0x00 +#define CMD_PACKET 0xA0 +#define CMD_READ_BUFFER 0xE4 +#define CMD_READ_DMA 0xC8 +#define CMD_READ_DMA_QUEUED 0xC7 +#define CMD_READ_MULTIPLE 0xC4 +#define CMD_READ_SECTORS 0x20 +#define CMD_READ_VERIFY_SECTORS 0x40 +#define CMD_RECALIBRATE 0x10 +#define CMD_SEEK 0x70 +#define CMD_SET_FEATURES 0xEF +#define CMD_SET_MULTIPLE_MODE 0xC6 +#define CMD_SLEEP1 0xE6 +#define CMD_SLEEP2 0x99 +#define CMD_STANDBY1 0xE2 +#define CMD_STANDBY2 0x96 +#define CMD_STANDBY_IMMEDIATE1 0xE0 +#define CMD_STANDBY_IMMEDIATE2 0x94 +#define CMD_WRITE_BUFFER 0xE8 +#define CMD_WRITE_DMA 0xCA +#define CMD_WRITE_DMA_QUEUED 0xCC +#define CMD_WRITE_MULTIPLE 0xC5 +#define CMD_WRITE_SECTORS 0x30 +#define CMD_WRITE_VERIFY 0x3C + +// CB_DH bits 7-4 OF THE DEVICE/HEAD REGISTER +#define ATA_DH_DEV0 0xE0 // select device 0 LBA MODE +#define ATA_DH_DEV1 0xF0 // select device 1 LBA MODE + #endif /* WDC_DRV_PATA_H_ */ \ No newline at end of file