Page 1 of 1

FDC prints junk?

Posted: Mon Jul 27, 2009 6:21 pm
by AUsername
Well my FDC driver fails for some reason. It loads the sector using the DMA but when I go to print out the data returned it's jumbled up parts of the sector. It appears to skip entire parts of the sector at random for no reason.

So I rewrote it from scratch (both the DMA "driver" and the FDC driver) and the same exact thing happens, same junk. It's just faster. (which is irrelevant)

Honestly I'm at a dead end. I've looked over the code many times and I don't see anything wrong. I would assume it's with the DMA but it looks fine to me.

DMA:

Code: Select all

void dma_mask_channel(uint8_t channel){
	if (channel<=4){
		outportb(0x0a,(1 << (channel-1)));
	}else{
		outportb(0xd4,(1 << (channel-5)));
	}
}

void dma_unmask(uint8_t channel){//Chan2=0x6
	if (channel<=4){
		outportb(0x0a,channel);
	}else{
		outportb(0xd4,channel);
	}
}

void dma_unmask_all(){
	outportb(0xdc,0xff);
}

void dma_reset(){
	outportb(0x0c,0xff);
}

void dma_reset_flipflop(){
	outportb(0xd8,0xff);
}

void dma_set_address(uint8_t low, uint8_t high){
	outportb(0x04,low);
	outportb(0x04,high);
}

void dma_set_count(uint8_t low, uint8_t high){
	outportb(0x05,low);
	outportb(0x05,high);
}

void dma_set_epr(uint8_t addr){
	outportb(0x81,addr);
}

export void _cdecl dma_set_read(){
	dma_mask_channel(2);
	outportb(0x0b,0x56);
	dma_unmask_all();
}

export void _cdecl dma_set_write(){
	dma_mask_channel(2);
	outportb(0x0b,0x5a);
	dma_unmask_all();
}

export bool _cdecl dma_initialize_floppy(uint8_t* buffer, unsigned length){
	union{
		uint8_t byte[4];//Lo[0], Mid[1], Hi[2]
		unsigned long l;
	}a, c;

	a.l=(unsigned)0x500;//buffer
	c.l=(unsigned)length-1;

	//Check for buffer issues
	if ((a.l >> 24) || (c.l >> 16) || (((a.l & 0xffff)+c.l) >> 16)){
#ifdef _DEBUG
		_asm{
			mov		eax, 0x1337
			cli
			hlt
		}
#endif
		return false;
	}

	dma_reset();//Hard reset
	dma_mask_channel(2);//Mask channel 2
	dma_reset_flipflop();//Flipflop reset

	dma_set_address(a.byte[0],a.byte[1]);//Buffer address
	dma_set_epr(a.byte[2]);//Set page register

	dma_reset_flipflop();//Flipflop reset

	dma_set_count(c.byte[0],c.byte[1]);//Set count
	
	outportb(0x0b,0x56);//Set the dma to read when initialized

	dma_unmask_all();//Unmask channel 2

	return true;
}
(Also it skips 3 bytes)

So I guess what I'm asking is does anyone see anything wrong with that?
If not, any ideas on what could possibly cause this?

Re: FDC prints junk?

Posted: Tue Jul 28, 2009 3:47 am
by Creature
Are you sure you placed the DMA buffer at a physical address below 16 MB? I believe the DMA requires it to be somewhere below that area. I'm also not sure about the 'dma_mask_channel' function, I never knew too much about bit shifting and such, but I'm not sure it's being done correctly. When I want to mask channel 2, this is what I do:

Code: Select all

WriteByte(0x0A, 0x06);
Your code gives this:

Code: Select all

WriteByte(0x0A, (1 << (channel - 1)));
Where if channel = 2, the byte written would be (1 << 1), which sets bit 1 and I believe is equal to 0x02. Again, I'm not sure about the DMA code, but it might be a problem.

Besides this, it could also be a problem with your floppy sector reading code (or whatever reading code and functions you've implemented), so it might be useful posting those as well.

Re: FDC prints junk?

Posted: Tue Jul 28, 2009 5:02 am
by -m32
Yeah, I think you need to read the Wiki very carefully: http://wiki.osdev.org/DMA

Re: FDC prints junk?

Posted: Tue Jul 28, 2009 7:34 am
by Dex
Also zero you DMA buffer to see if your driver works at all, as you could be printing random data at the buffer address.
Note: it should in most cases work or not work, not half work ;)