Tue, 14 Dec 2010 02:41:40 +0000
add CHS param checking (FDC), fix DMA address setting (DMA_XFER)
* Floppy controller wasn't checking CHS values. Fixed.
* DMA ADDRESS COUNT register was implemented completely wrong -- shifts and ANDmasks were wrong. Fixed.
Boot PROM and Loader now run to the point of booting the kernel!
src/main.c | file | annotate | diff | revisions | |
src/memory.c | file | annotate | diff | revisions | |
src/wd279x.c | file | annotate | diff | revisions |
1.1 --- a/src/main.c Mon Dec 13 03:00:43 2010 +0000 1.2 +++ b/src/main.c Tue Dec 14 02:41:40 2010 +0000 1.3 @@ -243,18 +243,18 @@ 1.4 d += wd2797_read_reg(&state.fdc_ctx, WD2797_REG_DATA); 1.5 1.6 // TODO: FIXME: if we get a pagefault, it NEEDS to be tagged as 'peripheral sourced'... this is a HACK! 1.7 - m68k_write_memory_16(state.dma_address << 1, d); 1.8 + m68k_write_memory_16(state.dma_address, d); 1.9 } else { 1.10 // Data write to FDC 1.11 // TODO: FIXME: if we get a pagefault, it NEEDS to be tagged as 'peripheral sourced'... this is a HACK! 1.12 - d = m68k_read_memory_16(state.dma_address << 1); 1.13 + d = m68k_read_memory_16(state.dma_address); 1.14 1.15 wd2797_write_reg(&state.fdc_ctx, WD2797_REG_DATA, (d >> 8)); 1.16 wd2797_write_reg(&state.fdc_ctx, WD2797_REG_DATA, (d & 0xff)); 1.17 } 1.18 1.19 // Increment DMA address 1.20 - state.dma_address++; 1.21 + state.dma_address+=2; 1.22 // Increment number of words transferred 1.23 num++; state.dma_count++; 1.24 } 1.25 @@ -262,7 +262,7 @@ 1.26 // Turn off DMA engine if we finished this cycle 1.27 if (state.dma_count >= 0x4000) { 1.28 printf("\tDMATRAN: transfer complete! dmaa=%06X, dmac=%04X\n", state.dma_address, state.dma_count); 1.29 - // apparently this isn't required...? 1.30 + // FIXME? apparently this isn't required...? 1.31 // state.dma_count = 0; 1.32 state.dmaen = false; 1.33 }
2.1 --- a/src/memory.c Mon Dec 13 03:00:43 2010 +0000 2.2 +++ b/src/memory.c Tue Dec 14 02:41:40 2010 +0000 2.3 @@ -596,10 +596,11 @@ 2.4 if (address & 1) { 2.5 data = 0x12; // no parity error, no line printer error, no irqs from FDD or HDD 2.6 data |= (state.fdc_ctx.irql) ? 0x08 : 0; // FIXME! HACKHACKHACK! shouldn't peek inside FDC structs like this 2.7 - data |= 0x04; // HDD interrupt, i.e. command complete -- HACKHACKHACK! 2.8 +// data |= 0x04; // HDD interrupt, i.e. command complete -- HACKHACKHACK! 2.9 } else { 2.10 data = 0; 2.11 } 2.12 + handled = true; 2.13 break; 2.14 case 0x080000: // Real Time Clock 2.15 break; 2.16 @@ -824,12 +825,12 @@ 2.17 case 0x0D0000: // DMA Address Register 2.18 if (address & 0x004000) { 2.19 // A14 high -- set most significant bits 2.20 - state.dma_address = (state.dma_address & 0xff) | ((address & 0x3fff) << 7); 2.21 + state.dma_address = (state.dma_address & 0x1fe) | ((address & 0x3ffe) << 8); 2.22 } else { 2.23 // A14 low -- set least significant bits 2.24 - state.dma_address = (state.dma_address & 0x3fff00) | (address & 0xff); 2.25 + state.dma_address = (state.dma_address & 0x3ffe00) | (address & 0x1fe); 2.26 } 2.27 - printf("WR DMA_ADDR, now %08X\n", state.dma_address); 2.28 + printf("WR32 DMA_ADDR %s, now %08X\n", address & 0x004000 ? "HI" : "LO", state.dma_address); 2.29 handled = true; 2.30 break; 2.31 case 0x0E0000: // Disk Control Register 2.32 @@ -1031,12 +1032,12 @@ 2.33 case 0x0D0000: // DMA Address Register 2.34 if (address & 0x004000) { 2.35 // A14 high -- set most significant bits 2.36 - state.dma_address = (state.dma_address & 0xff) | ((address & 0x3fff) << 7); 2.37 + state.dma_address = (state.dma_address & 0x1fe) | ((address & 0x3ffe) << 8); 2.38 } else { 2.39 // A14 low -- set least significant bits 2.40 - state.dma_address = (state.dma_address & 0x3fff00) | (address & 0xff); 2.41 + state.dma_address = (state.dma_address & 0x3ffe00) | (address & 0x1fe); 2.42 } 2.43 - printf("WR DMA_ADDR, now %08X\n", state.dma_address); 2.44 + printf("WR16 DMA_ADDR %s, now %08X\n", address & 0x004000 ? "HI" : "LO", state.dma_address); 2.45 handled = true; 2.46 break; 2.47 case 0x0E0000: // Disk Control Register 2.48 @@ -1235,12 +1236,12 @@ 2.49 case 0x0D0000: // DMA Address Register 2.50 if (address & 0x004000) { 2.51 // A14 high -- set most significant bits 2.52 - state.dma_address = (state.dma_address & 0xff) | ((address & 0x3fff) << 7); 2.53 + state.dma_address = (state.dma_address & 0x1fe) | ((address & 0x3ffe) << 8); 2.54 } else { 2.55 // A14 low -- set least significant bits 2.56 - state.dma_address = (state.dma_address & 0x3fff00) | (address & 0xff); 2.57 + state.dma_address = (state.dma_address & 0x3ffe00) | (address & 0x1fe); 2.58 } 2.59 - printf("WR DMA_ADDR, now %08X\n", state.dma_address); 2.60 + printf("WR08 DMA_ADDR %s, now %08X\n", address & 0x004000 ? "HI" : "LO", state.dma_address); 2.61 handled = true; 2.62 break; 2.63 case 0x0E0000: // Disk Control Register
3.1 --- a/src/wd279x.c Mon Dec 13 03:00:43 2010 +0000 3.2 +++ b/src/wd279x.c Tue Dec 14 02:41:40 2010 +0000 3.3 @@ -170,9 +170,9 @@ 3.4 // Get current status flags (set by last command) 3.5 // DRQ bit 3.6 if (ctx->cmd_has_drq) { 3.7 - printf("\tWDFDC rd sr, has drq, pos=%lu len=%lu\n", ctx->data_pos, ctx->data_len); 3.8 temp = ctx->status & ~0x03; 3.9 temp |= (ctx->data_pos < ctx->data_len) ? 0x02 : 0x00; 3.10 + printf("\tWDFDC rd sr, has drq, pos=%lu len=%lu, sr=0x%02X\n", ctx->data_pos, ctx->data_len, temp); 3.11 } else { 3.12 temp = ctx->status & ~0x01; 3.13 } 3.14 @@ -384,6 +384,20 @@ 3.15 ctx->head = (val & 0x02) ? 1 : 0; 3.16 printf("WD279X: READ SECTOR cmd=%02X chs=%d:%d:%d\n", cmd, ctx->track, ctx->head, ctx->sector); 3.17 // Read Sector or Read Sector Multiple 3.18 + 3.19 + // Check to see if the cyl, hd and sec are valid 3.20 + if ((ctx->track > (ctx->geom_tracks-1)) || (ctx->head > (ctx->geom_heads-1)) || (ctx->sector > ctx->geom_spt) || (ctx->sector == 0)) { 3.21 + fprintf(stderr, "*** WD2797 ALERT: CHS parameter limit exceeded! CHS=%d:%d:%d, maxCHS=%d:%d:%d\n", 3.22 + ctx->track, ctx->head, ctx->sector, 3.23 + ctx->geom_tracks-1, ctx->geom_heads-1, ctx->geom_spt); 3.24 + // CHS parameters exceed limits 3.25 + ctx->status = 0x10; // Record Not Found 3.26 + break; 3.27 + // Set IRQ only if IRQL has been cleared (no pending IRQs) 3.28 + ctx->irqe = ctx->irql ? ctx->irqe : true; 3.29 + ctx->irql = true; 3.30 + } 3.31 + 3.32 // reset data pointers 3.33 ctx->data_pos = ctx->data_len = 0; 3.34 3.35 @@ -395,7 +409,11 @@ 3.36 3.37 for (int i=0; i<temp; i++) { 3.38 // Calculate the LBA address of the required sector 3.39 - lba = ((((ctx->track * ctx->geom_heads) + ctx->head) * ctx->geom_spt) + ((ctx->sector + i - 1) % ctx->geom_spt)) * ctx->geom_secsz; 3.40 +// lba = ((((ctx->track * ctx->geom_heads) + ctx->head) * ctx->geom_spt) + ((ctx->sector + i - 1) % ctx->geom_spt)) * ctx->geom_secsz; 3.41 + // LBA = (C * nHeads * nSectors) + (H * nSectors) + S - 1 3.42 + lba = (((ctx->track * ctx->geom_heads * ctx->geom_spt) + (ctx->head * ctx->geom_spt) + ctx->sector) + i) - 1; 3.43 + // convert LBA to byte address 3.44 + lba *= ctx->geom_secsz; 3.45 printf("\tREAD lba = %lu\n", lba); 3.46 3.47 // Read the sector from the file 3.48 @@ -408,7 +426,7 @@ 3.49 ctx->status = 0; 3.50 // B6 = 0 3.51 // B5 = Record Type -- 1 = deleted, 0 = normal. We can't emulate anything but normal data blocks. 3.52 - // B4 = Record Not Found. We're not going to see this... FIXME-not emulated 3.53 + // B4 = Record Not Found. Basically, the CHS parameters are bullcrap. 3.54 // B3 = CRC Error. Not possible. 3.55 // B2 = Lost Data. Caused if DRQ isn't serviced in time. FIXME-not emulated 3.56 // B1 = DRQ. Data request.