1.1 diff -r 4c85846b09cd -r a392eb8f9806 src/memory.c 1.2 --- a/src/memory.c Sat Nov 17 19:13:08 2012 +0000 1.3 +++ b/src/memory.c Sat Nov 17 19:18:29 2012 +0000 1.4 @@ -144,7 +144,8 @@ 1.5 case MEM_KERNEL: \ 1.6 case MEM_PAGE_NO_WE: \ 1.7 /* kernel access or page not write enabled */ \ 1.8 - /* FIXME: which regs need setting? */ \ 1.9 + /* XXX: is this the correct value? */ \ 1.10 + state.genstat = 0x9BFF | (state.pie ? 0x0400 : 0); \ 1.11 fault = true; \ 1.12 break; \ 1.13 } \ 1.14 @@ -194,7 +195,8 @@ 1.15 case MEM_KERNEL: \ 1.16 case MEM_PAGE_NO_WE: \ 1.17 /* kernel access or page not write enabled */ \ 1.18 - /* FIXME: which regs need setting? */ \ 1.19 + /* XXX: is this the correct value? */ \ 1.20 + state.genstat = 0xDBFF | (state.pie ? 0x0400 : 0); \ 1.21 fault = true; \ 1.22 break; \ 1.23 } \ 1.24 @@ -213,6 +215,52 @@ 1.25 } while (0) 1.26 /*}}}*/ 1.27 1.28 +bool access_check_dma(int reading) 1.29 +{ 1.30 + // Check memory access permissions 1.31 + bool access_ok; 1.32 + switch (checkMemoryAccess(state.dma_address, !reading)) { 1.33 + case MEM_PAGEFAULT: 1.34 + // Page fault 1.35 + state.genstat = 0xABFF 1.36 + | (reading ? 0x4000 : 0) 1.37 + | (state.pie ? 0x0400 : 0); 1.38 + access_ok = false; 1.39 + break; 1.40 + 1.41 + case MEM_UIE: 1.42 + // User access to memory above 4MB 1.43 + // FIXME? Shouldn't be possible with DMA... assert this? 1.44 + state.genstat = 0xBAFF 1.45 + | (reading ? 0x4000 : 0) 1.46 + | (state.pie ? 0x0400 : 0); 1.47 + access_ok = false; 1.48 + break; 1.49 + 1.50 + case MEM_KERNEL: 1.51 + case MEM_PAGE_NO_WE: 1.52 + // Kernel access or page not write enabled 1.53 + /* XXX: is this correct? */ 1.54 + state.genstat = 0xBBFF 1.55 + | (reading ? 0x4000 : 0) 1.56 + | (state.pie ? 0x0400 : 0); 1.57 + access_ok = false; 1.58 + break; 1.59 + 1.60 + case MEM_ALLOWED: 1.61 + access_ok = true; 1.62 + break; 1.63 + } 1.64 + if (!access_ok) { 1.65 + state.bsr0 = 0x3C00; 1.66 + state.bsr0 |= (state.dma_address >> 16); 1.67 + state.bsr1 = state.dma_address & 0xffff; 1.68 + if (state.ee) m68k_set_irq(7); 1.69 + printf("BUS ERROR FROM DMA: genstat=%04X, bsr0=%04X, bsr1=%04X\n", state.genstat, state.bsr0, state.bsr1); 1.70 + } 1.71 + return (access_ok); 1.72 +} 1.73 + 1.74 // Logging macros 1.75 #define LOG_NOT_HANDLED_R(bits) \ 1.76 if (!handled) printf("unhandled read%02d, addr=0x%08X\n", bits, address); 1.77 @@ -275,9 +323,19 @@ 1.78 state.idmarw = ((data & 0x4000) == 0x4000); 1.79 state.dmaen = ((data & 0x8000) == 0x8000); 1.80 // This handles the "dummy DMA transfer" mentioned in the docs 1.81 - // TODO: access check, peripheral access 1.82 - if (!state.idmarw) 1.83 - WR32(state.base_ram, mapAddr(address, true), state.base_ram_size - 1, 0xDEAD); 1.84 + // disabled because it causes the floppy test to fail 1.85 +#if 0 1.86 + if (!state.idmarw){ 1.87 + if (access_check_dma(true)){ 1.88 + uint32_t newAddr = mapAddr(state.dma_address, true); 1.89 + // RAM access 1.90 + if (newAddr <= 0x1fffff) 1.91 + WR16(state.base_ram, newAddr, state.base_ram_size - 1, 0xFF); 1.92 + else if (address <= 0x3FFFFF) 1.93 + WR16(state.exp_ram, newAddr - 0x200000, state.exp_ram_size - 1, 0xFF); 1.94 + } 1.95 + } 1.96 +#endif 1.97 state.dma_count++; 1.98 handled = true; 1.99 break; 1.100 @@ -316,7 +374,6 @@ 1.101 case 0x0A0000: // Miscellaneous Control Register 1.102 ENFORCE_SIZE_W(bits, address, 16, "MISCCON"); 1.103 // TODO: handle the ctrl bits properly 1.104 - // TODO: &0x8000 --> dismiss 60hz intr 1.105 if (data & 0x8000){ 1.106 state.timer_enabled = 1; 1.107 }else{ 1.108 @@ -353,16 +410,30 @@ 1.109 handled = true; 1.110 break; 1.111 case 0x0E0000: // Disk Control Register 1.112 - ENFORCE_SIZE_W(bits, address, 16, "DISKCON"); 1.113 - // B7 = FDD controller reset 1.114 - if ((data & 0x80) == 0) wd2797_reset(&state.fdc_ctx); 1.115 - // B6 = drive 0 select -- TODO 1.116 - // B5 = motor enable -- TODO 1.117 - // B4 = HDD controller reset -- TODO 1.118 - // B3 = HDD0 select -- TODO 1.119 - // B2,1,0 = HDD0 head select 1.120 - handled = true; 1.121 - break; 1.122 + { 1.123 + bool fd_selected; 1.124 + bool hd_selected; 1.125 + ENFORCE_SIZE_W(bits, address, 16, "DISKCON"); 1.126 + // B7 = FDD controller reset 1.127 + if ((data & 0x80) == 0) wd2797_reset(&state.fdc_ctx); 1.128 + // B6 = drive 0 select 1.129 + fd_selected = (data & 0x40) != 0; 1.130 + // B5 = motor enable -- TODO 1.131 + // B4 = HDD controller reset 1.132 + if ((data & 0x10) == 0) wd2010_reset(&state.hdc_ctx); 1.133 + // B3 = HDD0 select 1.134 + hd_selected = (data & 0x08) != 0; 1.135 + // B2,1,0 = HDD0 head select -- TODO? 1.136 + if (hd_selected && !state.hd_selected){ 1.137 + state.fd_selected = false; 1.138 + state.hd_selected = true; 1.139 + }else if (fd_selected && !state.fd_selected){ 1.140 + state.hd_selected = false; 1.141 + state.fd_selected = true; 1.142 + } 1.143 + handled = true; 1.144 + break; 1.145 + } 1.146 case 0x0F0000: // Line Printer Data Register 1.147 break; 1.148 } 1.149 @@ -388,14 +459,17 @@ 1.150 case 0xE00000: // HDC, FDC, MCR2 and RTC data bits 1.151 case 0xF00000: 1.152 switch (address & 0x070000) { 1.153 - case 0x000000: // [ef][08]xxxx ==> WD1010 hard disc controller 1.154 + case 0x000000: // [ef][08]xxxx ==> WD2010 hard disc controller 1.155 + wd2010_write_reg(&state.hdc_ctx, (address >> 1) & 7, data); 1.156 + handled = true; 1.157 break; 1.158 case 0x010000: // [ef][19]xxxx ==> WD2797 floppy disc controller 1.159 - ENFORCE_SIZE_W(bits, address, 16, "FDC REGISTERS"); 1.160 + /*ENFORCE_SIZE_W(bits, address, 16, "FDC REGISTERS");*/ 1.161 wd2797_write_reg(&state.fdc_ctx, (address >> 1) & 3, data); 1.162 handled = true; 1.163 break; 1.164 case 0x020000: // [ef][2a]xxxx ==> Miscellaneous Control Register 2 1.165 + /*TODO: implement P5.1 second hard drive select*/ 1.166 break; 1.167 case 0x030000: // [ef][3b]xxxx ==> Real Time Clock data bits 1.168 break; 1.169 @@ -492,6 +566,7 @@ 1.170 case 0x070000: // Line Printer Status Register 1.171 data = 0x00120012; // no parity error, no line printer error, no irqs from FDD or HDD 1.172 data |= wd2797_get_irq(&state.fdc_ctx) ? 0x00080008 : 0; 1.173 + data |= wd2010_get_irq(&state.hdc_ctx) ? 0x00040004 : 0; 1.174 return data; 1.175 break; 1.176 case 0x080000: // Real Time Clock 1.177 @@ -563,9 +638,11 @@ 1.178 case 0xF00000: 1.179 switch (address & 0x070000) { 1.180 case 0x000000: // [ef][08]xxxx ==> WD1010 hard disc controller 1.181 + return (wd2010_read_reg(&state.hdc_ctx, (address >> 1) & 7)); 1.182 + 1.183 break; 1.184 case 0x010000: // [ef][19]xxxx ==> WD2797 floppy disc controller 1.185 - ENFORCE_SIZE_R(bits, address, 16, "FDC REGISTERS"); 1.186 + /*ENFORCE_SIZE_R(bits, address, 16, "FDC REGISTERS");*/ 1.187 return wd2797_read_reg(&state.fdc_ctx, (address >> 1) & 3); 1.188 break; 1.189 case 0x020000: // [ef][2a]xxxx ==> Miscellaneous Control Register 2 1.190 @@ -826,6 +903,7 @@ 1.191 } else if (address <= 0x3FFFFF) { 1.192 // RAM access 1.193 uint32_t newAddr = mapAddr(address, true); 1.194 + 1.195 if (newAddr <= 0x1fffff) 1.196 WR16(state.base_ram, newAddr, state.base_ram_size - 1, value); 1.197 else