src/wd279x.c

changeset 53
e1693c4b8a0c
parent 51
e5a92d7beecf
child 54
57c6ef81ae81
     1.1 diff -r a350dfa92895 -r e1693c4b8a0c src/wd279x.c
     1.2 --- a/src/wd279x.c	Sun Dec 05 16:20:00 2010 +0000
     1.3 +++ b/src/wd279x.c	Mon Dec 06 01:26:37 2010 +0000
     1.4 @@ -1,6 +1,7 @@
     1.5  #include <stdint.h>
     1.6  #include <stdbool.h>
     1.7  #include <malloc.h>
     1.8 +#include "musashi/m68k.h"
     1.9  #include "wd279x.h"
    1.10  
    1.11  /// WD2797 command constants
    1.12 @@ -164,12 +165,17 @@
    1.13  		case WD2797_REG_STATUS:		// Status register
    1.14  			// Read from status register clears IRQ
    1.15  			ctx->irql = false;
    1.16 +			ctx->irqe = false;
    1.17  
    1.18  			// Get current status flags (set by last command)
    1.19 -			temp = ctx->status;
    1.20  			// DRQ bit
    1.21 -			if (ctx->cmd_has_drq)
    1.22 +			if (ctx->cmd_has_drq) {
    1.23 +				printf("\tWDFDC rd sr, has drq, pos=%lu len=%lu\n", ctx->data_pos, ctx->data_len);
    1.24 +				temp = ctx->status & ~0x03;
    1.25  				temp |= (ctx->data_pos < ctx->data_len) ? 0x02 : 0x00;
    1.26 +			} else {
    1.27 +				temp = ctx->status & ~0x01;
    1.28 +			}
    1.29  			// FDC is busy if there is still data in the buffer
    1.30  			temp |= (ctx->data_pos < ctx->data_len) ? 0x01 : 0x00;	// if data in buffer, then DMA hasn't copied it yet, and we're still busy!
    1.31  																	// TODO: also if seek delay / read delay hasn't passed (but that's for later)
    1.32 @@ -184,9 +190,16 @@
    1.33  		case WD2797_REG_DATA:		// Data register
    1.34  			// If there's data in the buffer, return it. Otherwise return 0xFF.
    1.35  			if (ctx->data_pos < ctx->data_len) {
    1.36 +				// set IRQ if this is the last data byte
    1.37 +				if (ctx->data_pos == (ctx->data_len-1)) {
    1.38 +					// Set IRQ only if IRQL has been cleared (no pending IRQs)
    1.39 +					ctx->irqe = ctx->irql ? ctx->irqe : true;
    1.40 +					ctx->irql = true;
    1.41 +				}
    1.42  				// return data byte and increment pointer
    1.43  				return ctx->data[ctx->data_pos++];
    1.44  			} else {
    1.45 +				// command finished
    1.46  				return 0xff;
    1.47  			}
    1.48  
    1.49 @@ -205,6 +218,8 @@
    1.50  	bool is_type1 = false;
    1.51  	int temp;
    1.52  
    1.53 +	m68k_end_timeslice();
    1.54 +
    1.55  	switch (addr) {
    1.56  		case WD2797_REG_COMMAND:	// Command register
    1.57  			// write to command register clears interrupt request
    1.58 @@ -300,13 +315,16 @@
    1.59  				// 		TODO: Set a timer for seeks, and ONLY clear BUSY when that timer expires. Need periodics for that.
    1.60  				
    1.61  				// Set IRQ only if IRQL has been cleared (no pending IRQs)
    1.62 -				ctx->irqe = !ctx->irql;
    1.63 +				ctx->irqe = ctx->irql ? ctx->irqe : true;
    1.64  				ctx->irql = true;
    1.65  				return;
    1.66  			}
    1.67  
    1.68  			// That's the Type 1 (seek) commands sorted. Now for the others.
    1.69  
    1.70 +			// All these commands return the DRQ bit...
    1.71 +			ctx->cmd_has_drq = true;
    1.72 +
    1.73  			// If drive isn't ready, then set status B7 and exit
    1.74  			if (ctx->disc_image == NULL) {
    1.75  				ctx->status = 0x80;
    1.76 @@ -322,7 +340,7 @@
    1.77  					ctx->status = 0x40;
    1.78  
    1.79  					// Set IRQ only if IRQL has been cleared (no pending IRQs)
    1.80 -					ctx->irqe = !ctx->irql;
    1.81 +					ctx->irqe = ctx->irql ? ctx->irqe : true;
    1.82  					ctx->irql = true;
    1.83  
    1.84  					return;
    1.85 @@ -351,6 +369,7 @@
    1.86  					ctx->data[ctx->data_len++] = 0;	// TODO: IDAM CRC!
    1.87  					ctx->data[ctx->data_len++] = 0;
    1.88  
    1.89 +					ctx->status = 0;
    1.90  					// B6, B5 = 0
    1.91  					// B4 = Record Not Found. We're not going to see this... FIXME-not emulated
    1.92  					// B3 = CRC Error. Not possible.
    1.93 @@ -361,6 +380,7 @@
    1.94  
    1.95  				case CMD_READ_SECTOR:
    1.96  				case CMD_READ_SECTOR_MULTI:
    1.97 +					printf("WD279X: READ SECTOR chs=%d:%d:%d\n", ctx->track, ctx->head, ctx->sector);
    1.98  					// Read Sector or Read Sector Multiple
    1.99  					// reset data pointers
   1.100  					ctx->data_pos = ctx->data_len = 0;
   1.101 @@ -374,13 +394,16 @@
   1.102  					for (int i=0; i<temp; i++) {
   1.103  						// Calculate the LBA address of the required sector
   1.104  						lba = ((((ctx->track * ctx->geom_heads) + ctx->head) * ctx->geom_spt) + ((ctx->sector + i - 1) % ctx->geom_spt)) * ctx->geom_secsz;
   1.105 +						printf("\tREAD lba = %lu\n", lba);
   1.106  
   1.107  						// Read the sector from the file
   1.108  						fseek(ctx->disc_image, lba, SEEK_SET);
   1.109  						ctx->data_len += fread(&ctx->data[ctx->data_len], 1, ctx->geom_secsz, ctx->disc_image);
   1.110 +						printf("\tREAD len=%lu, pos=%lu, ssz=%d\n", ctx->data_len, ctx->data_pos, ctx->geom_secsz);
   1.111  						// TODO: check fread return value! if < secsz, BAIL! (call it a crc error or secnotfound maybe? also log to stderr)
   1.112  					}
   1.113  
   1.114 +					ctx->status = 0;
   1.115  					// B6 = 0
   1.116  					// B5 = Record Type -- 1 = deleted, 0 = normal. We can't emulate anything but normal data blocks.
   1.117  					// B4 = Record Not Found. We're not going to see this... FIXME-not emulated
   1.118 @@ -393,6 +416,7 @@
   1.119  				case CMD_READ_TRACK:
   1.120  					// Read Track
   1.121  					// TODO! implement this
   1.122 +					ctx->status = 0;
   1.123  					// B6, B5, B4, B3 = 0
   1.124  					// B2 = Lost Data. Caused if DRQ isn't serviced in time. FIXME-not emulated
   1.125  					// B1 = DRQ. Data request.
   1.126 @@ -408,6 +432,7 @@
   1.127  
   1.128  					// TODO: set "write pending" flag, and write LBA, and go from there.
   1.129  
   1.130 +					ctx->status = 0;
   1.131  					// B6 = Write Protect. FIXME -- emulate this!
   1.132  					// B5 = 0
   1.133  					// B4 = Record Not Found. We're not going to see this... FIXME-not emulated
   1.134 @@ -419,6 +444,7 @@
   1.135  
   1.136  				case CMD_FORMAT_TRACK:
   1.137  					// Write Track (aka Format Track)
   1.138 +					ctx->status = 0;
   1.139  					// B6 = Write Protect. FIXME -- emulate this!
   1.140  					// B5, B4, B3 = 0
   1.141  					// B2 = Lost Data. Caused if DRQ isn't serviced in time. FIXME-not emulated
   1.142 @@ -430,9 +456,10 @@
   1.143  					// Force Interrupt...
   1.144  					// Terminates current operation and sends an interrupt
   1.145  					// TODO!
   1.146 +					ctx->status = 0;
   1.147  					ctx->data_pos = ctx->data_len = 0;
   1.148  					// Set IRQ only if IRQL has been cleared (no pending IRQs)
   1.149 -					ctx->irqe = !ctx->irql;
   1.150 +					ctx->irqe = ctx->irql ? ctx->irqe : true;
   1.151  					ctx->irql = true;
   1.152  					break;
   1.153  			}
   1.154 @@ -453,6 +480,13 @@
   1.155  			// If we're processing a write command, and there's space in the
   1.156  			// buffer, allow the write.
   1.157  			if (ctx->data_pos < ctx->data_len) {
   1.158 +				// set IRQ if this is the last data byte
   1.159 +				if (ctx->data_pos == (ctx->data_len-1)) {
   1.160 +					// Set IRQ only if IRQL has been cleared (no pending IRQs)
   1.161 +					ctx->irqe = ctx->irql ? ctx->irqe : true;
   1.162 +					ctx->irql = true;
   1.163 +				}
   1.164 +
   1.165  				// store data byte and increment pointer
   1.166  				ctx->data[ctx->data_pos++] = val;
   1.167  			}