Exemplo n.º 1
0
uint8_t* floppy_read(uint32_t addr, uint8_t sectorc) {
    uint8_t cylinder = addr / CY_NUM;
    uint8_t head = (addr % CY_NUM)  / HE_NUM;
    uint8_t sector = ((addr % CY_NUM)  % HE_NUM) / SE_NUM + 1;
    uint8_t st, cy;
    floppy_control_motor(true);

    if(floppy_seek(cylinder, head, 0) != 0)
        return 0;

    prepare_floppy_DMA_read(sectorc);
    floppy_send_cmd(MT | MF | SK | READ_DATA);
    floppy_send_cmd(head << 2);
    floppy_send_cmd(cylinder);
    floppy_send_cmd(head);
    floppy_send_cmd(sector);
    floppy_send_cmd(2);
    floppy_send_cmd(sectorc); // read sector count
    floppy_send_cmd(0x1b);
    floppy_send_cmd(0xff);

    wait_floppy_irq();
    floppy_check_int(&st, &cy);

    // result phase
    for(uint32_t index_1 = 0 ; index_1 < 7; index_1++)
        floppy_read_byte();

    floppy_control_motor(false);
    return (uint8_t*) DMA_ADDR;
}
Exemplo n.º 2
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;
}
Exemplo n.º 3
0
uint8_t read_sector(uint8_t C,uint8_t H,uint8_t S) {
    wait_for_FDC();
    while(!floppy_motor);
    if(floppy_C != C) {
        floppy_seek(C);
    }
    init_floppy_DMA();
    send_floppy_command(FLOPPY_READ_CMD);
    send_floppy_data((H<<2)|FLOPPY_SELECT_A);
    send_floppy_data(C);
    send_floppy_data(H);
    send_floppy_data(S);
    send_floppy_data(2);
    send_floppy_data(1);//Sector Number
    send_floppy_data(0x1B);
    send_floppy_data(0xFF);
    floppy_interrupt_finished = 0;
    backup_eflags();
    sti();
    floppy_disable_other_interrupt();
    while(!floppy_interrupt_finished);
    floppy_enable_other_interrupt();
    restore_eflags();
    st0 = read_floppy_data();
    st1 = read_floppy_data();
    st2 = read_floppy_data();
    C = read_floppy_data();
    H = read_floppy_data();
    S = read_floppy_data();
    read_floppy_data();//Sector Number
    wait_for_FDC();
    if((st0>>6)||st1||st2) {
        return 0;
    }
}
Exemplo n.º 4
0
/* Low-level block device routine */
static int floppy_rw_blk(struct blkdev *bdev, int write,
				block_t blk, char *buf, size_t len)
{
	int head, track, sector;
	int tries = 3;
	long flags;

	if ( write ) {
		printk("floppy0: read-only device\n");
		return -1;
	}

try_again:
	if ( inb(dprts->dir) & DIR_CHAN ) {
		printk("floppy: disk change on read\n");
		return -1;
	}

	floppy_block(blk, &head, &track, &sector);
	floppy_seek(dprts, track);

	/* select data rate (is this redundant?) */
	outb(dprts->ccr, 0);

	/* Do the read */
	lock_irq(flags);
	dma_read(2, buf, 512);
	floppy_send(dprts, CMD_READ);
	floppy_send(dprts, head<<2);
	floppy_send(dprts, track);
	floppy_send(dprts, head);
	floppy_send(dprts, sector);
	floppy_send(dprts, 2);
	floppy_send(dprts, geom->spt);
	floppy_send(dprts, geom->g3_rw);
	floppy_send(dprts, 0xff);
	sleep_on(&floppyq);
	unlock_irq(flags);

	/* Success */
	if ( (status[0] & 0xc0) == 0 ) {
		if ( --len ) {
			blk++;
			buf+=512;
			goto try_again;
		}
		return 0;
	}

	if ( --tries ) {
		printk("floppy_rw_block: I/O err, try again\n");
		floppy_recal(dprts);
		goto try_again;
	}
	return -1;
}
Exemplo n.º 5
0
static int floppy_cylinder(int drive, int cylinder, floppy_io io_dir)
{
	uint8_t command = 0;
	int i; 
	const uint8_t flags = 0xC0; // Multitrack et MFM activés
	
	// Variables recevant les valeurs de retour de la lecture
	uint8_t st0, st1, st2, rcy, rhe, rse, bps;
	int error = 0;
	
	switch(io_dir)
	{
		case FLOPPY_WRITE:
			command = WRITE_DATA | flags;
			break;
		case FLOPPY_READ:
			command = READ_DATA | flags;
			break;
		default:
			kerr("Invalid io_dir (0x%x).", io_dir);
			return -1;
	}
	
	// On lit avec les deux têtes, on les met donc toutes en position
	if(floppy_seek(drive, cylinder, 0)) return -1;
	if(floppy_seek(drive, cylinder, 1)) return -1;
	
	// On s'accord 5 essais, totalement arbitraire, à calibrer donc.
	for(i=0; i<5; i++)
	{
		// Allumage moteur
		floppy_motor(drive, ON);
		
		// Initialisation DMA
		floppy_dma_init(io_dir);
		
		//TODO: Sleep pour attendre que le seek soit bien fini
		
		
		// Envoi de la commande
		//1) Commande
		//2) (head<<2)|drive
		//3) Numero du cylindre
		//4) head
		//5) Numero du premier secteur
		//6) Taille des secteur(2=512 bytes, ce qui est le cas pour toutes les floppy...)
		//7) Nombre de secteurs à lire
		//8) 0x1b (taille par défaut de GAP1)
		//9) 0xff (??)
		floppy_write_command(command);
		floppy_write_command(drive&0x03); // head = 0 dans le cas du MT, et drive&0x03 au cas ou drive > 3
		floppy_write_command(cylinder);
		floppy_write_command(0); // voir plus haut
		floppy_write_command(1); // On compte les secteurs a partir de 1
		floppy_write_command(2);
		floppy_write_command(18); // 18 secteurs par piste
		floppy_write_command(0x1b);
		floppy_write_command(0xff);
		
		floppy_wait_irq(); 
		
		// On verifie que la lecture c'est correctement déroulée
		
		// Informations de statut
		st0 = floppy_read_data();
		st1 = floppy_read_data();
		st2 = floppy_read_data();
		
		// Informations sur les CHS
		rcy = floppy_read_data(); // Cylindre
		rhe = floppy_read_data(); // Head
		rse = floppy_read_data(); // Secteur
		bps = floppy_read_data(); // Nomber de byte par secteur
		
		/* Traitement des erreurs repompée */
		if(st0 & 0xC0) {
			static const char * status[] =
			{ 0, "error", "invalid command", "drive not ready" };
			klog("floppy_do_sector: status = %s", status[st0 >> 6]);
			error = 1;
		}
		if(st1 & 0x80) {
			kerr("end of cylinder");
			error = 1;
		}
		if(st0 & 0x08) {
			kerr("drive not ready ");
			error = 1;
		}
		if(st1 & 0x20) {
			kerr("CRC error");
			error = 1;
		}
		if(st1 & 0x10) {
			kerr("controller timeout");
			error = 1;
		}
		if(st1 & 0x04) {
			kerr("no data found\n");
			error = 1;
		}
		if((st1|st2) & 0x01) {
			kerr("no address mark found");
			error = 1;
		}
		if(st2 & 0x40) {
			kerr("deleted address mark");
			error = 1;
		}
		if(st2 & 0x20) {
			kerr("CRC error in data");
			error = 1;
		}
		if(st2 & 0x10) {
			kerr("wrong cylinder");
			error = 1;
		}
		if(st2 & 0x04) {
			kerr("uPD765 sector not found");
			error = 1;
		}
		if(st2 & 0x02) {
			kerr("bad cylinder");
			error = 1;
		}
		if(bps != 0x2) {
			kerr("wanted 512B/sector, got %d", (1<<(bps+7)));
			error = 1;
		}
		if(st1 & 0x02) {
			kerr("not writable");
			error = 2;
		}

		if(!error) {
			floppy_motor(drive, OFF);
			return 0;
		}
		if(error > 1) {
			kerr("not retrying...(rcy = %0x%x, rhe = %0x%x, rse = %0x%x)", rcy, rhe, rse);
			floppy_motor(drive, OFF); 
			return -2;
		}
	
	}
	
	return 0;
}
Exemplo n.º 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);
}