Sat, 17 Nov 2012 22:26:53 +0000
Add support for MSR2, partial reads from GENSTAT
* GENSTAT is sometimes read in 8bit mode. Handle this properly.
* Add support for the MSR2 register (additional HDD head select bit only at
the moment)
src/memory.c | file | annotate | diff | revisions | |
src/wd2010.c | file | annotate | diff | revisions | |
src/wd2010.h | file | annotate | diff | revisions |
1.1 --- a/src/memory.c Sat Nov 17 22:15:23 2012 +0000 1.2 +++ b/src/memory.c Sat Nov 17 22:26:53 2012 +0000 1.3 @@ -472,7 +472,9 @@ 1.4 handled = true; 1.5 break; 1.6 case 0x020000: // [ef][2a]xxxx ==> Miscellaneous Control Register 2 1.7 - /*TODO: implement P5.1 second hard drive select*/ 1.8 + // MCR2 - UNIX PC Rev. P5.1 HDD head select b3 and potential HDD#2 select 1.9 + wd2010_write_reg(&state.hdc_ctx, UNIXPC_REG_MCR2, data); 1.10 + handled = true; 1.11 break; 1.12 case 0x030000: // [ef][3b]xxxx ==> Real Time Clock data bits 1.13 break; 1.14 @@ -546,8 +548,14 @@ 1.15 // I/O register space, zone A 1.16 switch (address & 0x0F0000) { 1.17 case 0x010000: // General Status Register 1.18 - ENFORCE_SIZE_R(bits, address, 16, "GENSTAT"); 1.19 - return ((uint32_t)state.genstat << 16) + (uint32_t)state.genstat; 1.20 + /* ENFORCE_SIZE_R(bits, address, 16, "GENSTAT"); */ 1.21 + if (bits == 32) { 1.22 + return ((uint32_t)state.genstat << 16) + (uint32_t)state.genstat; 1.23 + } else if (bits == 16) { 1.24 + return (uint16_t)state.genstat; 1.25 + } else { 1.26 + return (uint8_t)(state.genstat & 0xff); 1.27 + } 1.28 break; 1.29 case 0x030000: // Bus Status Register 0 1.30 ENFORCE_SIZE_R(bits, address, 16, "BSR0");
2.1 --- a/src/wd2010.c Sat Nov 17 22:15:23 2012 +0000 2.2 +++ b/src/wd2010.c Sat Nov 17 22:26:53 2012 +0000 2.3 @@ -102,6 +102,8 @@ 2.4 ctx->cylinder_low_reg = 0; 2.5 ctx->cylinder_high_reg = 0; 2.6 ctx->sdh = 0; 2.7 + ctx->mcr2_hdsel3 = 0; 2.8 + ctx->mcr2_ddrive1 = 0; 2.9 } 2.10 2.11 void wd2010_done(WD2010_CTX *ctx) 2.12 @@ -260,6 +262,17 @@ 2.13 2.14 /*cpu_log_enabled = 1;*/ 2.15 2.16 + if (addr == UNIXPC_REG_MCR2) { 2.17 + // The UNIX PC has an "MCR2" register with the following format: 2.18 + // [ 7..2 ][1][0] 2.19 + // Bits 7..2: Not used 2.20 + // Bit 1: DDRIVE1 (hard disk drive 1 select - not used?) 2.21 + // Bit 0: HDSEL3 (head-select bit 3) 2.22 + ctx->mcr2_hdsel3 = ((val & 1) == 1); 2.23 + ctx->mcr2_ddrive1 = ((val & 2) == 2); 2.24 + return; 2.25 + } 2.26 + 2.27 switch (addr & 0x07) { 2.28 case WD2010_REG_WRITE_PRECOMP_CYLINDER: 2.29 break; 2.30 @@ -313,7 +326,8 @@ 2.31 ctx->irq = true; 2.32 break; 2.33 } 2.34 - ctx->head = ctx->sdh & 0x07; 2.35 + // The SDH register provides 3 head select bits; the 4th comes from MCR2. 2.36 + ctx->head = (ctx->sdh & 0x07) + (ctx->mcr2_hdsel3 ? 8 : 0); 2.37 ctx->sector = ctx->sector_number; 2.38 2.39 ctx->formatting = cmd == CMD_WRITE_FORMAT;
3.1 --- a/src/wd2010.h Sat Nov 17 22:15:23 2012 +0000 3.2 +++ b/src/wd2010.h Sat Nov 17 22:26:53 2012 +0000 3.3 @@ -8,16 +8,16 @@ 3.4 3.5 /// WD2010 registers 3.6 typedef enum { 3.7 - WD2010_REG_ERROR = 1, ///< Error register 3.8 - WD2010_REG_WRITE_PRECOMP_CYLINDER = 1, ///< Write precompensation cylinder 3.9 - ///< register 3.10 - WD2010_REG_SECTOR_COUNT = 2, ///< Sector count register 3.11 - WD2010_REG_SECTOR_NUMBER = 3, ///< Sector number register 3.12 - WD2010_REG_CYLINDER_LOW = 4, ///< Low byte of cylinder 3.13 - WD2010_REG_CYLINDER_HIGH = 5, ///< High byte of cylinder 3.14 - WD2010_REG_SDH = 6, ///< Sector size, drive, and head 3.15 - WD2010_REG_STATUS = 7, ///< Status register 3.16 - WD2010_REG_COMMAND = 7, ///< Command register 3.17 + WD2010_REG_ERROR = 1, ///< Error register 3.18 + WD2010_REG_WRITE_PRECOMP_CYLINDER = 1, ///< Write precompensation cylinder register 3.19 + WD2010_REG_SECTOR_COUNT = 2, ///< Sector count register 3.20 + WD2010_REG_SECTOR_NUMBER = 3, ///< Sector number register 3.21 + WD2010_REG_CYLINDER_LOW = 4, ///< Low byte of cylinder 3.22 + WD2010_REG_CYLINDER_HIGH = 5, ///< High byte of cylinder 3.23 + WD2010_REG_SDH = 6, ///< Sector size, drive, and head 3.24 + WD2010_REG_STATUS = 7, ///< Status register 3.25 + WD2010_REG_COMMAND = 7, ///< Command register 3.26 + UNIXPC_REG_MCR2 = 255 ///< UNIX-PC MCR2 register (special!) 3.27 } WD2010_REG; 3.28 3.29 /// WD2010 emulator error codes 3.30 @@ -42,6 +42,8 @@ 3.31 uint8_t cylinder_high_reg, cylinder_low_reg; 3.32 // SDH register (sets sector size, drive number, and head number) 3.33 uint8_t sdh; 3.34 + // MCR2 register (LSB is HDSEL3 - head select bit 3) 3.35 + bool mcr2_hdsel3, mcr2_ddrive1; 3.36 // Sector number and count registers 3.37 int sector_number, sector_count; 3.38 // Last command has the multiple sector flag set?