Page 1 of 1
Floppy Reading Problem
Posted: Wed Aug 02, 2006 2:20 am
by Tolga
Hi. I wrote my floppy driver. For all functions, i looked to intel document. Now my read_sector function doing something with floppy. I setup DMA to 512 byte and address 0. But after reading function, im writing 512 byte character to screen from address 0. I understand that it is not readed. Can the problem be about DMA?
After Reading operation, Results;
Status Register 0 = 0;
Status Register 1 = 0;
Status Register 2 = 0;
Cylinder = 0;
Head = 0;
Sector = 2; (Im reading sector 1)
Re:Floppy Reading Problem
Posted: Wed Aug 02, 2006 4:37 am
by Pype.Clicker
do you mean "address 0" like in "bootsector" or like in "real-mode interrupt vector table" ?
Re:Floppy Reading Problem
Posted: Wed Aug 02, 2006 5:21 am
by Tolga
This process in pmode and im reading floppy sector 1. (First sector). And address 0 is memory address. (Real mode interrupt vector table area)
Re:Floppy Reading Problem
Posted: Wed Aug 02, 2006 7:49 am
by Tolga
DMA setup code:
Code: Select all
// Setup DMA (For 1 Sector)
void tfdc::setup_dma()
{
// Stop Interrupts
cli();
// Select DMA
dma.select_channel( 2 );
dma.set_ports();
// Disable Channel
dma.disable_channel();
// Clear Regs
dma.clear_flip_flop();
// Set Mode
dma.set_control_byte( dma_single_mode, dma_address_increment, dma_auto_initialization, dma_read_transfer );
// Set Offset
dma.set_address( 0 );
// Set Size
dma.set_transfer_length( 512 );
// Set Mask (Enable Channel)
dma.enable_channel();
// Enable Interrupts
sti();
}
Re:Floppy Reading Problem
Posted: Wed Aug 02, 2006 2:45 pm
by Tolga
Everybody designing file system. :'( After i solve this problem, i too. Please help me. Im looking to results. I think there is no error at reading. can the problem be about DMA?
Re:Floppy Reading Problem
Posted: Wed Aug 02, 2006 4:04 pm
by Slasher
We need the code in full to know if its DMA that is the problem.
eg
dma.set_ports();
can't help without knowing what you are doing in the functions.
Re:Floppy Reading Problem
Posted: Wed Aug 02, 2006 10:07 pm
by Tolga
Full of DMA.CPP
Code: Select all
// DMA HEADER CODE
// PREPROCESSOR
#include "dma.h"
#include "system.h"
// DEFINITONS
// = Channels & Ports =
// 8 Bit
#define dma_channel_0_address_port 0x00
#define dma_channel_0_count_port 0x01
#define dma_channel_0_page_port 0x87
#define dma_channel_1_address_port 0x02
#define dma_channel_1_count_port 0x03
#define dma_channel_1_page_port 0x83
#define dma_channel_2_address_port 0x04
#define dma_channel_2_count_port 0x05
#define dma_channel_2_page_port 0x81
#define dma_channel_3_address_port 0x06
#define dma_channel_3_count_port 0x07
#define dma_channel_3_page_port 0x82
// 16 Bit
#define dma_channel_4_address_port 0xC0
#define dma_channel_4_count_port 0xC2
#define dma_channel_4_page_port 0x8F
#define dma_channel_5_address_port 0xC4
#define dma_channel_5_count_port 0xC6
#define dma_channel_5_page_port 0x8B
#define dma_channel_6_address_port 0xC8
#define dma_channel_6_count_port 0xCA
#define dma_channel_6_page_port 0x89
#define dma_channel_7_address_port 0xCC
#define dma_channel_7_count_port 0xCE
#define dma_channel_7_page_port 0x8A
// = Write Mode =
#define dma_8_bit_write_mode 0x0B
#define dma_16_bit_write_mode 0xD6
// = Single Mask Register =
#define dma_8_bit_single_mask_register 0x0A
#define dma_16_bit_single_mask_register 0xD4
// = Clear Byte Pointer =
#define dma_8_bit_clear_byte_pointer 0x0C
#define dma_16_bit_clear_byte_pointer 0xD8
// CLASS CODE
// Select Channel
void tdma::select_channel( unsigned char dma_channel_number )
{
// Control
if(dma_channel_number < 8)
dma_channel = dma_channel_number;
}
// Set Ports
void tdma::set_ports()
{
// Set Ports
switch(dma_channel)
{
case 0:
dma_address_port = dma_channel_0_address_port;
dma_count_port = dma_channel_0_count_port;
dma_page_port = dma_channel_0_page_port;
break;
case 1:
dma_address_port = dma_channel_1_address_port;
dma_count_port = dma_channel_1_count_port;
dma_page_port = dma_channel_1_page_port;
break;
case 2:
dma_address_port = dma_channel_2_address_port;
dma_count_port = dma_channel_2_count_port;
dma_page_port = dma_channel_2_page_port;
break;
case 3:
dma_address_port = dma_channel_3_address_port;
dma_count_port = dma_channel_3_count_port;
dma_page_port = dma_channel_3_page_port;
break;
case 4:
dma_address_port = dma_channel_4_address_port;
dma_count_port = dma_channel_4_count_port;
dma_page_port = dma_channel_4_page_port;
break;
case 5:
dma_address_port = dma_channel_5_address_port;
dma_count_port = dma_channel_5_count_port;
dma_page_port = dma_channel_5_page_port;
break;
case 6:
dma_address_port = dma_channel_6_address_port;
dma_count_port = dma_channel_6_count_port;
dma_page_port = dma_channel_6_page_port;
break;
case 7:
dma_address_port = dma_channel_7_address_port;
dma_count_port = dma_channel_7_count_port;
dma_page_port = dma_channel_7_page_port;
break;
}
// Register
if(dma_channel < 4)
{
dma_mode_register = dma_8_bit_write_mode;
dma_mask_register = dma_8_bit_single_mask_register;
dma_clear_register = dma_8_bit_clear_byte_pointer;
}
else
{
dma_mode_register = dma_16_bit_write_mode;
dma_mask_register = dma_16_bit_single_mask_register;
dma_clear_register = dma_16_bit_clear_byte_pointer;
}
}
// Enable Channel
void tdma::enable_channel()
{
// Enable Channel
outport( dma_mask_register, (dma_channel % 4) );
}
// Disable Channel
void tdma::disable_channel()
{
// Disable Channel
outport( dma_mask_register, 4 + (dma_channel % 4) );
}
// Clear Flip Flop
void tdma::clear_flip_flop()
{
// Clear Flip Flop
outport( dma_clear_register, 0 );
}
// Set Transfer Length
void tdma::set_transfer_length( unsigned short tlength )
{
// Assign
dma_transfer_length = tlength;
// Set Transfer Length
outport( dma_count_port, ((tlength - 1) & 0xFF) );
outport( dma_count_port, ((tlength - 1) >> 8) & 0xFF );
}
// Set Control Byte
void tdma::set_control_byte( unsigned char mode_selection, unsigned char addr_inc_dec, unsigned char auto_int, unsigned char transfer_type )
{
// Set Control Byte
outport( dma_mode_register, mode_selection + addr_inc_dec + auto_int + transfer_type + dma_channel );
}
// Set Memory Address
void tdma::set_address( unsigned long maddr )
{
// Variables
unsigned short offset_addr;
unsigned char page_addr;
// Assign
dma_memory_address = maddr;
// Calculate
offset_addr = maddr & 0xFFFF;
page_addr = (maddr >> 16) & 0xFF;
// Control
if(dma_channel > 3)
{
offset_addr = offset_addr >> 1;
}
// Send
outport( dma_page_port, page_addr );
outport( dma_address_port, (offset_addr & 0xFF) );
outport( dma_address_port, (offset_addr >> 8) & 0xFF );
}
Re:Floppy Reading Problem
Posted: Thu Aug 03, 2006 5:10 am
by Tolga
I wrote the code. Is there any reply?
Re:Floppy Reading Problem
Posted: Thu Aug 03, 2006 8:47 am
by Kemp
Just a quick note for the future, with long code listings it's usually considered polite to attach them rather than dump them in the post.
Re:Floppy Reading Problem
Posted: Thu Aug 03, 2006 10:53 am
by Tolga
Thanks for warning. But i need help for pursuance of my os.
Re:Floppy Reading Problem
Posted: Fri Aug 04, 2006 6:03 am
by Pype.Clicker
Maybe there are people here that can tell you what's been wrong with your DMA transfer "just like that", but when it come to floppy,
i can't.
So what i'd try to see is:
A) whether the floppy actually undertsood the command or not (i guess the fact the 'next sector' is two is a good clue, tough i cannot be assured).
B) whether the DMA did transfer things or not. Iirc, you should have some "byte counter" associated with each DMA channel, right ? if the channel was properly programmed and the transfer did take place, you should end up with a "remaining byte count" of 0 in the DMA registers.
C) whether the data you transferred were written or not. the internal debugger of bochs or qemu should help you do that.
If i can afford a suggestion, i'd say using the realmode IVT may not be the best location around... I'd rather use anything else as a transfer buffer (including using the VRAM directly as buffer
Re:Floppy Reading Problem
Posted: Fri Aug 04, 2006 7:25 am
by Tolga
1. I found the problem. I used DMA_Write(01b) for DMA transfer type and it has been running. But i dont understand. Is "DMA_Write"'s mean that write to memory? (I understand that write to disk; and this is wrong idea.
2. If i want to read many sectors, must i do recalibration, start motor and others for each sector reading?
Re:Floppy Reading Problem
Posted: Fri Aug 04, 2006 7:48 pm
by blip
1. According to the OsFaq, 01b would mean read from device and write to memory.
2. If you keep the motor going, you don't need to start it again. Recalibrate only on error conditions and don't infinitely retry operations.
Pype.Clicker: Does that actually work? At any rate, I don't think it's a good idea to try DMA'ing to VRAM for testing like this. I don't think it would work, but I've never actually tried, and even if it did I wouldn't count on it working on every machine out there. Maybe it would overwrite the SMI handler and data on some machines?
Re:Floppy Reading Problem
Posted: Sat Aug 05, 2006 4:24 pm
by Pype.Clicker
@blip: honnestly i see no reason why it wouldn't work. If you were requesting the BIOS to load a bmp from floppy sectors straight on screen, that'd be what you'll be doing, right ?
That's not like if DMA chip was somehow hardwired with your main memory. It just initiates memory read/write cycles, and i don't see why issueing cycles to 0xB8000 would be different from issueing cycles to 0x08000. I've done it in the past, and have even been using DMA to move stuff from VRAM to VRAM to implement a DMA-assisted scrolling (well, that was just before i learnt about VGA registers
)
Now, maybe there exist some odd laptops where something magic occurs when you write things from the CPU to 0xB8000 and where those things wouldn't occur if you write directly from a IO device such as floppy, HDD or whatever. If you have the proof of such evil laptop existence, that just comformts me that i'm going to focus more on nintendo DS than PC in the next years.