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 }