// 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; }
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; }