add CHS param checking (FDC), fix DMA address setting (DMA_XFER)

Tue, 14 Dec 2010 02:41:40 +0000

author
Philip Pemberton <philpem@philpem.me.uk>
date
Tue, 14 Dec 2010 02:41:40 +0000
changeset 57
feb84193a43a
parent 56
b3f309d46e97
child 58
85cc6101b587

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