src/wd279x.c

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