Page 1 of 1

FDC error: cannot find ID address mark

Posted: Tue Dec 14, 2010 7:59 am
by johank
Hi all,

Frustratingly, I keep on encountering 'real PC' errors with my FDC code that do not encounter under Bochs, both when booting from an image file and when booting from floppy. When reading a sector, using a FDC_READ (0x06) command, all is well in Bochs but two PCs, both an old 486 and a new Pentium 4, complain of a missing ID address mark.

I use WinImage to create an image, inserting files to it, and either run Bochs to use the image or write the image on a floppy (using Windows XP) and boot from floppy. I found some issues on the web on Win XP and the above ID address mark error, but I doubt whether it denotes the same problem.

Here's the relevant part of the code:

Code: Select all

void floppy_read(unsigned char head, unsigned char cylinder, void *address)
{
	int i, retries = 5;
	while (retries)
	{
		set_system_timer(FDC_TIMER, 1000);			/* timeout on FDC activity */
		fdc_motor_on();
		if (!implied_seeks)							/* to be used on older drives */
			floppy_seek(head, cylinder);
		setup_DMA_channel(FDC_DMA, 0x44, 0x2400, (unsigned int) address);	
		/* to mem, single transfer, 0x2400 bytes = 18 sectors */
		fdc_sendbyte(FDC_READ | 0x60); 				/* read command MFM/SK set MT clear */
		fdc_sendbyte(head * 4);						/* bits 0 and 1 denote drive number ( = 0) */
		fdc_sendbyte(cylinder);						/* send head */
		fdc_sendbyte(head);							/* resend head */
		fdc_sendbyte(1);							/* first sector */
		fdc_sendbyte(2);							/* sector size = 512 */
		fdc_sendbyte(18);							/* 18 sectors per cylinder */
		fdc_sendbyte(27);							/* GPL gap length */
		fdc_sendbyte(0xFF);							/* DTL special code (ff = not used) */
		while ((get_system_timer(FDC_TIMER)) && (fdc_done == 0))
			;										/* wait till fdc isr signals fdc ready */
		fdc_done = 0;								/* reset fdc-done flag */
		if (!get_system_timer(FDC_TIMER))			/* timer zero's out - no good - retry */
		{
			panic(KERN_NOTICE, "Timeout on floppy read");
			floppy_error = FDC_READ_TIMEOUT;
			retries--;
			break;
		}
		
		for (i = 0; i < 7; i++)						/* get the status bytes */
			fdc_statusbytes[i] = fdc_readbyte();
		
		if ((fdc_statusbytes[0] & 0xC0) != 0x00)	/* any error indicated? */
		{
			panic(KERN_NOTICE, "Read error in FDC driver\n%s", FDC_status_error(fdc_statusbytes[0], 
				fdc_statusbytes[1], fdc_statusbytes[2]));
			panic(KERN_NOTICE, "Retrying to read");
			floppy_error = FDC_READ_ERROR;
			retries--;
		}
		else										/* all's well! */
		{
			floppy_error = NO_ERROR;
			retries = 0;
		}
	}
}
Has any of you encountered similar problems before?

Best,
Johan

Re: FDC error: cannot find ID address mark

Posted: Tue Dec 14, 2010 11:14 am
by M2004
First thing that crosses my mind: Is the timer delay long enough?

regards
Mac2004

Re: FDC error: cannot find ID address mark

Posted: Tue Dec 14, 2010 11:18 am
by Brendan
Hi,
johank wrote:Has any of you encountered similar problems before?
I vaguely remember writing some code to auto-detect media formats, where it'd try different data rates until it found one that was able to read the first sector of the disk. I'd assume that using the wrong data rate would cause a "missing address mark" error (as the drive can't read anything from the disk), and I also wouldn't be surprised if Bochs didn't emulate different data rates properly (e.g. just loads sectors without checking if you've set the data rate correctly).

Note: the default data rate is 250 Kbps, which is mostly useless (only used for 360 KiB single-sided floppies and 720 KiB double sided floppies). For 1200 KiB and 1440 KiB floppies you want to change the data rate to 500 Kbps (in the "data rate select register"). Every time you change the data rate you also need to calculate new values for HLT/HUT/SRT and set them with the "specify" command (which is a pain in the neck if you support dual drives with potentially different media).

Anyway, I'm only guessing - the problem could be something else, and could even be something like a faulty floppy disk.


Cheers,

Brendan

Re: FDC error: cannot find ID address mark

Posted: Tue Dec 14, 2010 11:19 am
by Brendan
Hi,
mac2004 wrote:First thing that crosses my mind: Is the timer delay long enough?
Doh! Timing is a likely problem too - e.g. not having any delay after "fdc_motor_on();"...


Cheers,

Brendan

Re: FDC error: cannot find ID address mark

Posted: Tue Dec 14, 2010 11:33 am
by M2004
Brendan wrote: Doh! Timing is a likely problem too - e.g. not having any delay after "fdc_motor_on();"...
Floppies are slow and need quite long delays.

Regards
Mac2004

Re: FDC error: cannot find ID address mark

Posted: Tue Dec 14, 2010 11:41 am
by johank
Hi all,

thanks for your feedback up so far!

Re: timing: the motor_on function has a 0.5s delay (the calling process is put to sleep for 0.5s). The timeout is 50 seconds or so, which is reasonbly generous I think.

Re: data rate: indeed I had set it to 250 KiB and the error vanished!

However, a new error occurs: cannot find sector ID in st1 and wrong cylinder detected in st2...

But at least I'm getting somewhere!

best
Johan