Troubles with the floppy driver

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
User avatar
Karlosoft
Member
Member
Posts: 277
Joined: Thu Feb 14, 2008 10:46 am
Location: Italy
Contact:

Troubles with the floppy driver

Post by Karlosoft »

This is the code used in the brokenthorn tutorials for the floppy driver support. I simply changed some things to fit it on my code.
The problem is that it doesn't work. When I request to read a sector the screen is filled with 512 0.
timer_wait is a function wich compare the ticks of pit with the value given, the pit is working with a divisor of 100.

I think some changes I did, hide one or more bug.

Code: Select all

#include "system.h"
//****************************************************************************
//**
//**    flpydsk.cpp
//**		-Floppy Disk driver
//**
//****************************************************************************
//============================================================================
//    IMPLEMENTATION HEADERS
//============================================================================


//============================================================================
//    IMPLEMENTATION PRIVATE DEFINITIONS / ENUMERATIONS / SIMPLE TYPEDEFS
//============================================================================

/*
**	Controller I/O Ports. Please see chapter for additional ports
*/

enum FLPYDSK_IO {

	FLPYDSK_DOR		=	0x3f2,
	FLPYDSK_MSR		=	0x3f4,
	FLPYDSK_FIFO	=	0x3f5,
	FLPYDSK_CTRL	=	0x3f7
};

/**
*	Bits 0-4 of command byte. Please see chapter for additional commands
*/

enum FLPYDSK_CMD {

	FDC_CMD_READ_TRACK	=	2,
	FDC_CMD_SPECIFY		=	3,
	FDC_CMD_CHECK_STAT	=	4,
	FDC_CMD_WRITE_SECT	=	5,
	FDC_CMD_READ_SECT	=	6,
	FDC_CMD_CALIBRATE	=	7,
	FDC_CMD_CHECK_INT	=	8,
	FDC_CMD_FORMAT_TRACK=	0xd,
	FDC_CMD_SEEK		=	0xf
};

/**
*	Additional command masks. Can be masked with above commands
*/

enum FLPYDSK_CMD_EXT {

	FDC_CMD_EXT_SKIP		=	0x20,	//00100000
	FDC_CMD_EXT_DENSITY		=	0x40,	//01000000
	FDC_CMD_EXT_MULTITRACK	=	0x80	//10000000
};

/*
**	Digital Output Register
*/

enum FLPYDSK_DOR_MASK {

	FLPYDSK_DOR_MASK_DRIVE0			=	0,	//00000000	= here for completeness sake
	FLPYDSK_DOR_MASK_DRIVE1			=	1,	//00000001
	FLPYDSK_DOR_MASK_DRIVE2			=	2,	//00000010
	FLPYDSK_DOR_MASK_DRIVE3			=	3,	//00000011
	FLPYDSK_DOR_MASK_RESET			=	4,	//00000100
	FLPYDSK_DOR_MASK_DMA			=	8,	//00001000
	FLPYDSK_DOR_MASK_DRIVE0_MOTOR	=	16,	//00010000
	FLPYDSK_DOR_MASK_DRIVE1_MOTOR	=	32,	//00100000
	FLPYDSK_DOR_MASK_DRIVE2_MOTOR	=	64,	//01000000
	FLPYDSK_DOR_MASK_DRIVE3_MOTOR	=	128	//10000000
};

/**
*	Main Status Register
*/

enum FLPYDSK_MSR_MASK {

	FLPYDSK_MSR_MASK_DRIVE1_POS_MODE	=	1,	//00000001
	FLPYDSK_MSR_MASK_DRIVE2_POS_MODE	=	2,	//00000010
	FLPYDSK_MSR_MASK_DRIVE3_POS_MODE	=	4,	//00000100
	FLPYDSK_MSR_MASK_DRIVE4_POS_MODE	=	8,	//00001000
	FLPYDSK_MSR_MASK_BUSY				=	16,	//00010000
	FLPYDSK_MSR_MASK_DMA				=	32,	//00100000
	FLPYDSK_MSR_MASK_DATAIO				=	64, //01000000
	FLPYDSK_MSR_MASK_DATAREG			=	128	//10000000
};

/**
*	Controller Status Port 0
*/

enum FLPYDSK_ST0_MASK {

	FLPYDSK_ST0_MASK_DRIVE0		=	0,		//00000000	=	for completness sake
	FLPYDSK_ST0_MASK_DRIVE1		=	1,		//00000001
	FLPYDSK_ST0_MASK_DRIVE2		=	2,		//00000010
	FLPYDSK_ST0_MASK_DRIVE3		=	3,		//00000011
	FLPYDSK_ST0_MASK_HEADACTIVE	=	4,		//00000100
	FLPYDSK_ST0_MASK_NOTREADY	=	8,		//00001000
	FLPYDSK_ST0_MASK_UNITCHECK	=	16,		//00010000
	FLPYDSK_ST0_MASK_SEEKEND	=	32,		//00100000
	FLPYDSK_ST0_MASK_INTCODE	=	64		//11000000
};

/*
** LPYDSK_ST0_MASK_INTCODE types
*/

enum FLPYDSK_ST0_INTCODE_TYP {

	FLPYDSK_ST0_TYP_NORMAL		=	0,
	FLPYDSK_ST0_TYP_ABNORMAL_ERR=	1,
	FLPYDSK_ST0_TYP_INVALID_ERR	=	2,
	FLPYDSK_ST0_TYP_NOTREADY	=	3
};

/**
*	GAP 3 sizes
*/

enum FLPYDSK_GAP3_LENGTH {

	FLPYDSK_GAP3_LENGTH_STD = 42,
	FLPYDSK_GAP3_LENGTH_5_14= 32,
	FLPYDSK_GAP3_LENGTH_3_5= 27
};

/*
**	Formula: 2^sector_number * 128, where ^ denotes "to the power of"
*/

enum FLPYDSK_SECTOR_DTL {

	FLPYDSK_SECTOR_DTL_128	=	0,
	FLPYDSK_SECTOR_DTL_256	=	1,
	FLPYDSK_SECTOR_DTL_512	=	2,
	FLPYDSK_SECTOR_DTL_1024	=	4
};

/**
*	Constants
*/

//! floppy irq
const int FLOPPY_IRQ = 6;

//! sectors per track
const int FLPY_SECTORS_PER_TRACK = 18;

//! dma tranfer buffer starts here and ends at 0x1000+64k
//! You can change this as needed. It must be below 16MB and in idenitity mapped memory!
const int DMA_BUFFER = 0x1000;

//============================================================================
//    IMPLEMENTATION PRIVATE CLASS PROTOTYPES / EXTERNAL CLASS REFERENCES
//============================================================================
//============================================================================
//    IMPLEMENTATION PRIVATE STRUCTURES / UTILITY CLASSES
//============================================================================
//============================================================================
//    IMPLEMENTATION REQUIRED EXTERNAL REFERENCES (AVOID)
//============================================================================

//! used to wait in miliseconds

//============================================================================
//    IMPLEMENTATION PRIVATE DATA
//============================================================================

//! current working drive. Defaults to 0 which should be fine on most systems
static uint8	_CurrentDrive = 0;

//! set when IRQ fires
static volatile uint8 _FloppyDiskIRQ = 0;

//============================================================================
//    INTERFACE DATA
//============================================================================
//============================================================================
//    IMPLEMENTATION PRIVATE FUNCTION PROTOTYPES
//============================================================================
//============================================================================
//    IMPLEMENTATION PRIVATE FUNCTIONS
//============================================================================

/**
*	DMA Routines.
**	The DMA (Direct Memory Access) controller allows the FDC to send data to the DMA,
**	which can put the data in memory. While the FDC can be programmed to not use DMA,
**  it is not very well supported on emulators or virtual machines. Because of this, we
**  will be using the DMA for data transfers. The DMA is a complex controller, because of
**  this we will cover it in the next tutorial. For now, please do not worry about the DMA
**  routines to much :)
*/

//! initialize DMA to use phys addr 84k-128k
void flpydsk_initialize_dma () {

	outportb (0x0a,0x06);	//mask dma channel 2
	outportb (0xd8,0xff);	//reset master flip-flop
	outportb (0x04, 0);     //address=0x1000 
	outportb (0x04, 0x10);
	outportb (0xd8, 0xff);  //reset master flip-flop
	outportb (0x05, 0xff);  //count to 0x23ff (number of bytes in a 3.5" floppy disk track)
	outportb (0x05, 0x23);
	outportb (0x80, 0);     //external page register = 0
	outportb (0x0a, 0x02);  //unmask dma channel 2
}

//! prepare the DMA for read transfer
void flpydsk_dma_read () {

	outportb (0x0a, 0x06); //mask dma channel 2
	outportb (0x0b, 0x56); //single transfer, address increment, autoinit, read, channel 2
	outportb (0x0a, 0x02); //unmask dma channel 2
}

//! prepare the DMA for write transfer
void flpydsk_dma_write () {

	outportb (0x0a, 0x06); //mask dma channel 2
	outportb (0x0b, 0x5a); //single transfer, address increment, autoinit, write, channel 2
	outportb (0x0a, 0x02); //unmask dma channel 2
}

/**
*	Basic Controller I/O Routines
*/

//! return fdc status
uint8 flpydsk_read_status () {

	//! just return main status register
	return inportb (FLPYDSK_MSR);
}

//! write to the fdc dor
void flpydsk_write_dor (uint8 val ) {

	//! write the digital output register
	outportb (FLPYDSK_DOR, val);
}

//! send command byte to fdc
void flpydsk_send_command (uint8 cmd) {

	//! wait until data register is ready. We send commands to the data register
	for (int i = 0; i < 500; i++ )
		if ( flpydsk_read_status () & FLPYDSK_MSR_MASK_DATAREG )
			return outportb (FLPYDSK_FIFO, cmd);
}

//! get data from fdc
uint8 flpydsk_read_data () {

	//! same as above function but returns data register for reading
	for (int i = 0; i < 500; i++ )
		if ( flpydsk_read_status () & FLPYDSK_MSR_MASK_DATAREG )
			return inportb (FLPYDSK_FIFO);

	return 0;
}

//! write to the configuation control register
void flpydsk_write_ccr (uint8 val) {

	//! write the configuation control
	outportb (FLPYDSK_CTRL, val);
}

/**
*	Interrupt Handling Routines
*/

//! wait for irq to fire
inline void flpydsk_wait_irq () {

	//! wait for irq to fire
	while ( _FloppyDiskIRQ == 0)
		;
	_FloppyDiskIRQ = 0;
}


//!	floppy disk irq handler
void i86_flpy_irq (struct regs *r) {
	_FloppyDiskIRQ = 1;
}

/**
*	Controller Command Routines
*/

//! check interrupt status command
void flpydsk_check_int (uint32* st0, uint32* cyl) {

	flpydsk_send_command (FDC_CMD_CHECK_INT);

	*st0 = flpydsk_read_data ();
	*cyl = flpydsk_read_data ();
}

//! turns the current floppy drives motor on/off
void flpydsk_control_motor (bool b) {

	//! sanity check: invalid drive
	if (_CurrentDrive > 3)
		return;

	uint32 motor = 0;

	//! select the correct mask based on current drive
	switch (_CurrentDrive) {

		case 0:
			motor = FLPYDSK_DOR_MASK_DRIVE0_MOTOR;
			break;
		case 1:
			motor = FLPYDSK_DOR_MASK_DRIVE1_MOTOR;
			break;
		case 2:
			motor = FLPYDSK_DOR_MASK_DRIVE2_MOTOR;
			break;
		case 3:
			motor = FLPYDSK_DOR_MASK_DRIVE3_MOTOR;
			break;
	}

	//! turn on or off the motor of that drive
	if (b)
		flpydsk_write_dor (_CurrentDrive | motor | FLPYDSK_DOR_MASK_RESET | FLPYDSK_DOR_MASK_DMA);
	else
		flpydsk_write_dor (FLPYDSK_DOR_MASK_RESET);

	//! in all cases; wait a little bit for the motor to spin up/turn off
	timer_wait (20);
}

//! configure drive
void flpydsk_drive_data (uint32 stepr, uint32 loadt, uint32 unloadt, bool dma ) {

	uint32 data = 0;

	//! send command
	flpydsk_send_command (FDC_CMD_SPECIFY);
	data = ( (stepr & 0xf) << 4) | (unloadt & 0xf);
		flpydsk_send_command (data);
	data = (loadt) << 1 | (dma==false) ? 0 : 1;
		flpydsk_send_command (data);
}

//! calibrates the drive
int flpydsk_calibrate (uint32 drive) {

	uint32 st0, cyl;

	if (drive >= 4)
		return -2;

	//! turn on the motor
	flpydsk_control_motor (true);

	for (int i = 0; i < 10; i++) {

		//! send command
		flpydsk_send_command ( FDC_CMD_CALIBRATE );
		flpydsk_send_command ( drive );
		flpydsk_wait_irq ();
		flpydsk_check_int ( &st0, &cyl);

		//! did we fine cylinder 0? if so, we are done
		if (!cyl) {

			flpydsk_control_motor (false);
			return 0;
		}
	}

	flpydsk_control_motor (false);
	return -1;
}

//! disable controller
void flpydsk_disable_controller () {

	flpydsk_write_dor (0);
}

//! enable controller
void flpydsk_enable_controller () {

	flpydsk_write_dor ( FLPYDSK_DOR_MASK_RESET | FLPYDSK_DOR_MASK_DMA);
}

//! reset controller
void flpydsk_reset () {

	uint32 st0, cyl;

	//! reset the controller
	flpydsk_disable_controller ();
	flpydsk_enable_controller ();
	flpydsk_wait_irq ();

	//! send CHECK_INT/SENSE INTERRUPT command to all drives
	for (int i=0; i<4; i++)
		flpydsk_check_int (&st0,&cyl);

	//! transfer speed 500kb/s
	flpydsk_write_ccr (0);

	//! pass mechanical drive info. steprate=3ms, unload time=240ms, load time=16ms
	flpydsk_drive_data (3,16,240,true);

	//! calibrate the disk
	flpydsk_calibrate ( _CurrentDrive );
}

//! read a sector
void flpydsk_read_sector_imp (uint8 head, uint8 track, uint8 sector) {

	uint32 st0, cyl;

	//! set the DMA for read transfer
	flpydsk_dma_read ();

	//! read in a sector
	flpydsk_send_command (
				FDC_CMD_READ_SECT | FDC_CMD_EXT_MULTITRACK | FDC_CMD_EXT_SKIP | FDC_CMD_EXT_DENSITY);
	flpydsk_send_command ( head << 2 | _CurrentDrive );
	flpydsk_send_command ( track);
	flpydsk_send_command ( head);
	flpydsk_send_command ( sector);
	flpydsk_send_command ( FLPYDSK_SECTOR_DTL_512 );
	flpydsk_send_command ( ( ( sector + 1 ) >= FLPY_SECTORS_PER_TRACK ) ? FLPY_SECTORS_PER_TRACK : sector + 1 );
	flpydsk_send_command ( FLPYDSK_GAP3_LENGTH_3_5 );
	flpydsk_send_command ( 0xff );

	//! wait for irq
	flpydsk_wait_irq ();

	//! read status info
	for (int j=0; j<7; j++)
		flpydsk_read_data ();

	//! let FDC know we handled interrupt
	flpydsk_check_int (&st0,&cyl);
}

//! seek to given track/cylinder
int flpydsk_seek ( uint32 cyl, uint32 head ) {

	uint32 st0, cyl0;

	if (_CurrentDrive >= 4)
		return -1;

	for (int i = 0; i < 10; i++ ) {

		//! send the command
		flpydsk_send_command (FDC_CMD_SEEK);
		flpydsk_send_command ( (head) << 2 | _CurrentDrive);
		flpydsk_send_command (cyl);

		//! wait for the results phase IRQ
		flpydsk_wait_irq ();
		flpydsk_check_int (&st0,&cyl0);

		//! found the cylinder?
		if ( cyl0 == cyl)
			return 0;
	}

	return -1;
}

//============================================================================
//    INTERFACE FUNCTIONS
//============================================================================

//! convert LBA to CHS
void flpydsk_lba_to_chs (int lba,int *head,int *track,int *sector) {

   *head = ( lba % ( FLPY_SECTORS_PER_TRACK * 2 ) ) / ( FLPY_SECTORS_PER_TRACK );
   *track = lba / ( FLPY_SECTORS_PER_TRACK * 2 );
   *sector = lba % FLPY_SECTORS_PER_TRACK + 1;
}

//! install floppy driver
void flpydsk_install () {

	//! install irq handler
    irq_install_handler(6, i86_flpy_irq);

	//! initialize the DMA for FDC
	flpydsk_initialize_dma ();

	//! reset the fdc
	flpydsk_reset ();

	//! set drive information
	flpydsk_drive_data (13, 1, 0xf, true);
}

//! set current working drive
void flpydsk_set_working_drive (uint8 drive) {

	if (drive < 4)
		_CurrentDrive = drive;
}

//! get current working drive
uint8 flpydsk_get_working_drive () {

	return _CurrentDrive;
}

//! read a sector
uint8* flpydsk_read_sector (int sectorLBA) {

	if (_CurrentDrive >= 4)
		return 0;

	//! convert LBA sector to CHS
	int head=0, track=0, sector=1;
	flpydsk_lba_to_chs (sectorLBA, &head, &track, &sector);

	//! turn motor on and seek to track
	flpydsk_control_motor (true);
	if (flpydsk_seek (track, head) != 0)
		return 0;

	//! read sector and turn motor off
	flpydsk_read_sector_imp (head, track, sector);
	flpydsk_control_motor (false);

	//! warning: this is a bit hackish
	return (uint8*) DMA_BUFFER;
}

//============================================================================
//    INTERFACE CLASS BODIES
//============================================================================
//****************************************************************************
//**
//**    END[flpydsk.cpp]
//**
//****************************************************************************
User avatar
neon
Member
Member
Posts: 1567
Joined: Sun Feb 18, 2007 7:28 pm
Contact:

Re: Troubles with the floppy driver

Post by neon »

Hello,

I recommend separating the DMA code from the floppy driver and dynamically allocating memory for it. This is done in the latest working copy of the software.

How are you using the driver? What changes have you made? Does any of the routines return an error? Does the demo work "as-is"?
OS Development Series | Wiki | os | ncc
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}
User avatar
Karlosoft
Member
Member
Posts: 277
Joined: Thu Feb 14, 2008 10:46 am
Location: Italy
Contact:

Re: Troubles with the floppy driver

Post by Karlosoft »

I will do as you say. I have never tried the original code because I use gcc and not visual studio, so in order to compile it I should change a lots of things, and the demo as-is in my code can't work. So I changed the routine called when the 6th line of pic is on, the irq_wait and the flpdsk_install function. The other code is the same (except the typedef, and the name of sleep changed with timer_wait). No error, the routine works but the memory from 0x1000 is empty (or better filled of 0)
User avatar
Karlosoft
Member
Member
Posts: 277
Joined: Thu Feb 14, 2008 10:46 am
Location: Italy
Contact:

Re: Troubles with the floppy driver

Post by Karlosoft »

I tried an other different fdc driver, but like the first it doesn't work. All let me think that the DMA doesn't work at all on my previous code. My kernel must have some mistakes I can't see.
User avatar
Karlosoft
Member
Member
Posts: 277
Joined: Thu Feb 14, 2008 10:46 am
Location: Italy
Contact:

Re: Troubles with the floppy driver

Post by Karlosoft »

This is my os, part of it written on the bran's tutorial, other mine. If anyone has a solution please write me here :)

Ps. I have not updated the comments so they still are the original ones, sometimes wrong...
Attachments
smile.zip
(27.12 KiB) Downloaded 54 times
User avatar
bewing
Member
Member
Posts: 1401
Joined: Wed Feb 07, 2007 1:45 pm
Location: Eugene, OR, US

Re: Troubles with the floppy driver

Post by bewing »

OK, I'll take a look at it on rebochs, and see if I can spot what is happening.
User avatar
ehenkes
Member
Member
Posts: 124
Joined: Mon Mar 23, 2009 3:15 am
Location: Germany
Contact:

Re: Troubles with the floppy driver

Post by ehenkes »

I experienced problems with the autoinit bit at DMA. Better not to set that, and initialize directly before the read process.

Code: Select all

/// autoinit (2^4 = 16 = 0x10) creates problems with MS Virtual PC and on real hardware!
/// hence, it is not used here, but reinitialization is used before read/write

// prepare the DMA for read transfer
void flpydsk_dma_read()
{
    outportb(0x0a, 0x06); // mask dma channel 2
    outportb(0x0b, 0x46); // single transfer, address increment, read, channel 2 // without autoinit
    outportb(0x0a, 0x02); // unmask dma channel 2
}
The real transfer process has its own initialization of DMA:

Code: Select all

// read: operation = 0; write: operation = 1
int32_t flpydsk_transfer_sector(uint8_t head, uint8_t track, uint8_t sector, uint8_t operation)
{
    uint32_t st0, cyl;
    flpydsk_initialize_dma(); // <------ 

    if (operation == 0) // read a sector
    {
        flpydsk_dma_read();
        flpydsk_send_command(FDC_CMD_READ_SECT | FDC_CMD_EXT_MULTITRACK | FDC_CMD_EXT_SKIP | FDC_CMD_EXT_DENSITY);
    }
    if (operation == 1) // write a sector
    {
        flpydsk_dma_write();
        flpydsk_send_command(FDC_CMD_WRITE_SECT | FDC_CMD_EXT_MULTITRACK | FDC_CMD_EXT_DENSITY);
    }

    flpydsk_send_command(head << 2 | CurrentDrive->ID);
    flpydsk_send_command(track);
    flpydsk_send_command(head);
    flpydsk_send_command(sector);
    flpydsk_send_command(FLPYDSK_SECTOR_DTL_512);
    flpydsk_send_command(FLPY_SECTORS_PER_TRACK);
    flpydsk_send_command(FLPYDSK_GAP3_LENGTH_3_5);
    flpydsk_send_command(0xFF);
    flpydsk_wait_irq();
    int32_t retVal;
    for (uint8_t j=0; j<7; ++j)
    {
        int32_t val = flpydsk_read_data(); // read status info: ST0 ST1 ST2 C H S Size(2: 512 Byte)
        if ((j==6) && (val==2)) // value 2 means 512 Byte
        {
            retVal = 0;
        }
        else
        {
            retVal = -1;
        }
    }
    flpydsk_check_int(&st0,&cyl); // inform FDC that we handled interrupt
    return retVal;
}
User avatar
Karlosoft
Member
Member
Posts: 277
Joined: Thu Feb 14, 2008 10:46 am
Location: Italy
Contact:

Re: Troubles with the floppy driver

Post by Karlosoft »

I changed the code but it still doesn't work.
Now I will look for mistakes in the irq.cpp file. Perhaps there is something wrong there
User avatar
Karlosoft
Member
Member
Posts: 277
Joined: Thu Feb 14, 2008 10:46 am
Location: Italy
Contact:

Re: Troubles with the floppy driver

Post by Karlosoft »

Code: Select all

void flpydsk_initialize_dma () {

   outportb (0x0a,0x06);   //mask dma channel 2
   outportb (0xd8,0xff);   //reset master flip-flop
   outportb (0x04, 0);     //address=0x1000
   outportb (0x04, 0x10);
   outportb (0xd8, 0xff);  //reset master flip-flop
   outportb (0x05, 0xff);  //count to 0x23ff (number of bytes in a 3.5" floppy disk track)
   outportb (0x05, 0x23);
   outportb (0x80, 0);     //external page register = 0
   outportb (0x0a, 0x02);  //unmask dma channel 2
}

Shouldn't be

Code: Select all

void flpydsk_initialize_dma () {

   outportb (0x0a,0x06);   //mask dma channel 2
   outportb (0x0c,0xff);   //reset master flip-flop
   outportb (0x04, 0);     //address=0x1000
   outportb (0x04, 0x10);
   outportb (0x0c, 0xff);  //reset master flip-flop
   outportb (0x05, 0xff);  //count to 0x23ff (number of bytes in a 3.5" floppy disk track)
   outportb (0x05, 0x23);
   outportb (0x81, 0);     //external page register = 0
   outportb (0x0a, 0x02);  //unmask dma channel 2
}

User avatar
ehenkes
Member
Member
Posts: 124
Joined: Mon Mar 23, 2009 3:15 am
Location: Germany
Contact:

Re: Troubles with the floppy driver

Post by ehenkes »

outportb (0x80, 0); //external page register = 0
Sure that this is correct?

I use:

Code: Select all

void flpydsk_initialize_dma()
{
    outportb(0x0a, 0x06);   // mask dma channel 2
    outportb(0xd8, 0xFF);   // reset master flip-flop
    outportb(0x04, 0x00);   // DMA buffer address 0x1000
    outportb(0x04, 0x10);
    outportb(0xd8, 0xFF);   // reset master flip-flop
    outportb(0x05, 0xFF);   // count to 0x23FF (number of bytes in a 3.5" floppy disk track: 18*512)
    outportb(0x05, 0x23);

    outportb(0x81, 0x00);   // external page register = 0
    outportb(0x0a, 0x02);   // unmask dma channel 2
}
User avatar
bewing
Member
Member
Posts: 1401
Joined: Wed Feb 07, 2007 1:45 pm
Location: Eugene, OR, US

Re: Troubles with the floppy driver

Post by bewing »

Karlosoft's second post is correct. And (as in his second post) the Master flipflop reset (for channels 0 to 3) is not at IO port 0xd8. It is at port 0xc.
User avatar
ehenkes
Member
Member
Posts: 124
Joined: Mon Mar 23, 2009 3:15 am
Location: Germany
Contact:

Re: Troubles with the floppy driver

Post by ehenkes »

could you please show a correct flpydsk_initialize_dma() ?

http://wiki.osdev.org/DMA#The_Flip-Flop
0x0C (channel 0-3) 0xD8 (channel 4-8) Flip-Flop Reset Register

please cf.:
http://www.lowlevel.eu/wiki/DMA#.C3.9Cb ... .2FO-Ports
http://www.brokenthorn.com/Resources/OSDev21.html

both recommend 0xd8 ! Please check whether osdev.org wiki is correct.
User avatar
bewing
Member
Member
Posts: 1401
Joined: Wed Feb 07, 2007 1:45 pm
Location: Eugene, OR, US

Re: Troubles with the floppy driver

Post by bewing »

ehenkes wrote:could you please show a correct flpydsk_initialize_dma() ?
He did. The second copy in his last post.
http://wiki.osdev.org/DMA#The_Flip-Flop
0x0C (channel 0-3) 0xD8 (channel 4-8) Flip-Flop Reset Register

please cf.:
http://www.lowlevel.eu/wiki/DMA#.C3.9Cb ... .2FO-Ports
http://www.brokenthorn.com/Resources/OSDev21.html

both recommend 0xd8 ! Please check whether osdev.org wiki is correct.
You are getting confused between "channel number" and which DMA controller is the "slave" or "Master". Channel 4-7 is "master" for historical reasons. Channel 2 is the floppy controller, so IO port 0xc is correct, and our wiki is correct.
User avatar
ehenkes
Member
Member
Posts: 124
Joined: Mon Mar 23, 2009 3:15 am
Location: Germany
Contact:

Re: Troubles with the floppy driver

Post by ehenkes »

0xd8 works correct, too. Therefore, both ports lead to reset, if needed.
It also works without resetting the slave's flipflop :mrgreen:
Post Reply