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 --- 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.