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 }