Example #1
0
/*******************************************************************************
 * void floppy_reset()
 * 
 * This resets the floppy (duh!) into a known condition.
 * 
 * Date:	December 31, 2004
 * *****************************************************************************/
void floppy_reset()
{
	outportb(FDC_DOR, 0);
	
	floppy_mtick = 0;
	floppy_motor = false;
	
	/*disable interrupt*/
	outportb(FDC_DRS, 0);
	
	/*reenable interrupts*/
	outportb(FDC_DOR, 0x0C);
	
	/*the reset triggered an interrupt, wait for it to be handled*/
	floppy_done = true;

	floppy_wait(true);
	
	/*specify driv timings*/
	floppy_sendbyte(CMD_SPECIFY);
	floppy_sendbyte(0xDF);
	floppy_sendbyte(0x02);
	
	/*clear the "disk change" status */
	floppy_seek(1);
	floppy_recalibrate();
	floppy_dchange = false;
}
Example #2
0
/*******************************************************************************
 * void floppy_recalibrate()
 * 
 * This recalibrates the FDC.
 * 
 * Date:	December 31, 2004
 * *****************************************************************************/
void floppy_recalibrate()
{
	/*turn the motor on*/
	floppy_motor_start();
	
	/*send command bytes*/
	floppy_sendbyte(CMD_RECAL);
	floppy_sendbyte(0);
	
	/*wait until seek if finished*/
	floppy_wait(true);
	
	/*turn the motor off*/
	floppy_motor_stop();
}
Example #3
0
/*******************************************************************************
 * void floppy_seek(int track)
 * 
 * This causes the floppy head to seek to the given track so that data can either
 * be written or read from it.
 * 
 * Parameters:
 * 	1) int track
 * 		This is the track that we want to seek to.
 * 
 * Date:	December 31, 2004
 * *****************************************************************************/
bool floppy_seek(int track)
{
	///check to see if we've already seeked to 'track'
	if (floppy_track == track)
		return true;
	
	///send command bytes
	floppy_sendbyte(CMD_SEEK);
	floppy_sendbyte(0);
	floppy_sendbyte(track);
	
	///wait until seek is finished
	if (!floppy_wait(true))
		return false;		///timeout
	
	///wait for the head to settle
	sleep(FLOPPY_SLEEP_TIME);
	
	///make sure that seek worked
	if ((floppy_sr0 != 0x20) || (floppy_track != track))
		return false;
	else
		return true;
}
Example #4
0
int floppy_rw_sector(uint_t drive, uint8_t sector, uint8_t head, uint8_t cylinder, uintptr_t buffer, int write)
{
	int a;
alku:
	if (drive >= MAX_DRIVES || !floppy_drives[drive].type) {
		return -1;
	}

	if (inportb(FLOPPY_FIRST + DIGITAL_INPUT_REGISTER) & 0x80) {
		/* disk was changed */
		floppy_seek_track(drive, 1);
		floppy_calibrate(drive);
		floppy_motor_off(drive);
		if (inportb(FLOPPY_FIRST + DIGITAL_INPUT_REGISTER) & 0x80) {
			kprintf("FDD: No floppy in fd%u\n", drive);
			return -2;
		} else {
			kprintf("FDD: Floppy changed, trying again...\n");
			goto alku;
		}
	}

	if (floppy_seek_track(drive, cylinder))
	if (floppy_seek_track(drive, cylinder))
	if (floppy_seek_track(drive, cylinder)) {
		return -1; /* three seeks? */
	}

	/* floppy_seek_track actually starts motor already, but... */
	floppy_motor_on(drive);

	if (!(inportb(FLOPPY_FIRST + MAIN_STATUS_REGISTER) & 0x20)) {
		panic("Non-dma floppy transfer?\n");
	}

	/* block size */
	floppy_init_dma(buffer, 512, write);

	kwait(0, 1000 * floppy_params.head_settle_time);
	floppy_wait();

	prepare_wait_irq(FLOPPY_IRQ);
	floppy_command(write ? WRITE_DATA : READ_DATA);
	floppy_command((head << 2) | drive);
	floppy_command(cylinder);
	floppy_command(head);
	floppy_command(sector);
	floppy_command(floppy_params.bytes_per_sector);  /*sector size = 128*2^size*/
	floppy_command(floppy_params.sectors_per_track); /*last sector*/
	floppy_command(floppy_params.gap_length);        /*27 default gap3 value*/
	floppy_command(floppy_params.data_length);       /*default value for data length*/

	//kprintf("FDD: BPS: %u, SPT: %u, GL: %u, DL: %u\n", floppy_params.bytes_per_sector, floppy_params.sectors_per_track, floppy_params.gap_length, floppy_params.data_length);

	wait_irq(FLOPPY_IRQ);
	//kprintf("We got values ");
	for (a = 0; a < 7; a++) { /* TODO: Put these values somewhere? */
		floppy_wait_data();
		inportb(FLOPPY_FIRST + DATA_FIFO);
		//kprintf("%d ", inportb(FLOPPY_FIRST + DATA_FIFO));
	}
	//kprintf(" from floppy controller after reading\n");
	floppy_prepare_motor_off(drive);
	return 0;
}
Example #5
0
void floppy_command(uint8_t command)
{
	floppy_wait();
	outportb(FLOPPY_FIRST + DATA_FIFO, command);
}
Example #6
0
/*******************************************************************************
 * bool floppy_rw(int block, unsigned char *blockbuff, 
 * 					unsigned char read, unsigned long nosectors)
 * 
 * Since the read and write to a floppy disk is not that much different, most of
 * the code is the same.  The only difference is dependent on what the 'read' 
 * variable is set as.
 * 
 * Parameters:
 * 	1) int block
 * 		This is the block that we want to read.
 * 	2) unsigned char *blockbuff
 * 		This is the buffer that we want it read into or written out to.  The size 
 * 		of this buffer should be 512 * nosectors, as each sector read in is 512 
 * 		bytes
 * 	3) unsigned char read
 * 		Are we going to read or write to this block.
 * 	4) unsigned long nosectors
 * 		The number of sectors that we want to be read in.
 * 
 * Return value:
 * 	This returns where or not the read/write was successfull.
 * 
 * Date:	December 31, 2004
 * *****************************************************************************/
bool floppy_rw(int block, unsigned char *blockbuff, unsigned char read, unsigned long nosectors)
{
	int head;
	int track;
	int sector;
	int tries;
	int copycount=0;
	unsigned char *p_track_buffer = (unsigned char*)floppy_dma_address;
	unsigned char *p_block_buffer = blockbuff;
	
	///convert logical address into physical address
	floppy_block2hts(block , &head, &track, &sector);
	
	///start the floppy motor
	floppy_motor_start();
	
	if (!read && blockbuff)
		///copy data from the data buffer into the track buffer
		for (copycount=0; copycount<(nosectors*512); copycount++)
			*(p_track_buffer++) = *(p_block_buffer++);
	
	for (tries = 0; tries < 3; tries++)
	{
		///check for disk change
		if (inportb(FDC_DIR) & 0x80)
		{
			floppy_dchange = true;
			floppy_seek(1);
			floppy_recalibrate();
			floppy_motor_stop();
			ERROR_MSG(("FDC: Disk change detected. Trying again."));
			return floppy_rw(block, blockbuff, read, nosectors);
		}
		
		///move head to the right track
		if (!floppy_seek(track))
		{
			floppy_motor_stop();
			ERROR_MSG(("FDC: Seek error"));
			return false;
		}
		
		///program data rate (500Kb/s)
		outportb(FDC_CCR, 0);
		
		///send command
		if (read)
		{
			dma_xfer(2, (unsigned long)floppy_dma_address, nosectors*512, false);
			floppy_sendbyte(CMD_READ);
		} else {
			dma_xfer(2, (unsigned long)floppy_dma_address, nosectors*512, true);
			floppy_sendbyte(CMD_WRITE);
		}
		
		floppy_sendbyte(head << 2);
		floppy_sendbyte(track);
		floppy_sendbyte(head);
		floppy_sendbyte(sector);
		floppy_sendbyte(2);
		floppy_sendbyte(floppy_geometry.spt);
		
		if (floppy_geometry.spt == DG144_SPT)
			floppy_sendbyte(DG144_GAP3RW);
		else
			floppy_sendbyte(DG168_GAP3RW);
		
		floppy_sendbyte(0xff);
		
		///wait for commmand completion
		if (!floppy_wait(true)) {
			ERROR_MSG(("Timed out, trying operation again after reset"));
			floppy_reset();
			return floppy_rw(block, blockbuff, read, nosectors);
		}
		
		///let's see if the transfer worked
		if ((floppy_status[0] & 0xC0) == 0) break;
		
		///it didn't work.  try again
		floppy_recalibrate();
	}
	
	floppy_motor_stop();
	
	if (read && blockbuff)
	{
		///copy data from track buffer into data buffer
		p_block_buffer = blockbuff;
		p_track_buffer = (unsigned char *)floppy_dma_address;
		for (copycount = 0; copycount <(nosectors*512); copycount++)
		{
			*p_block_buffer = *p_track_buffer;
			p_block_buffer++;
			p_track_buffer++;
		}
	}
	
	return (tries != 3);
}