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