src/memory.c

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