src/memory.c

changeset 112
a392eb8f9806
parent 108
5f7faf5ecbf4
child 113
d3bb6a6a04b7
     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