Ejemplo n.º 1
0
// Repositionne la tête de lecture sur le cylindre 0
int floppy_calibrate()
{
	int i, st0, cy1 = -1;
	int drive = floppy_get_current_drive();
	
	// Allumer le moteur
	floppy_motor(ON);
	
	// On essaye 5 fois (oui c'est totalement arbitraire)
	for(i=0; i<5; i++)
	{
		// Le recalibrage déclenche l'IRQ, on se prépare donc à attendre l'IRQ
		floppy_reset_irq();
		
		// Procedure de calibrage:
		// On envoi dans un premier temps la commande RECALIBRATE,
		// puis on envoi le numero du lecteur que l'on veut recalibrer
		floppy_write_command(RECALIBRATE);
		floppy_write_command(drive);
		
		// On attend la réponse
		floppy_wait_irq();
		
		// une fois l'IRQ arrivée, on peut récuperer les données de retour via SENSE_INTERRUPT
		floppy_sense_interrupt(&st0, &cy1);
		
		if(st0 & 0xC0)
		{
			static const char * status[] =
			{ 0, "error", "invalid", "drive" };
			klog("floppy_recalibrate: status = %s.", status[st0 >> 6]);
			klog("\tST0:0x%x.\nCY1:0x%x.", st0, cy1);
			continue;
		}
	
		if(!cy1) // si cy1=0, on a bien atteint le cylindre 0 et on peut arreter la calibration
		{
			floppy_motor(OFF);
			return 0;
		}
		
	}
	kerr("floppy_recalibrate: failure.");
	
	floppy_motor(OFF);
	
	return -1;
}
Ejemplo n.º 2
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;
}