int floppy_seek_track(uint_t drive, uint_t track) { if (drive >= MAX_DRIVES) { return -1; } if (track == floppy_drives[drive].track) { return 0; } floppy_motor_on(drive); prepare_wait_irq(FLOPPY_IRQ); floppy_command(SEEK); floppy_command(drive); floppy_command(track); wait_irq(FLOPPY_IRQ); floppy_drive_seeked = drive; floppy_sense_interrupt(); if (track != floppy_drives[drive].track) { kprintf("FDD: ERROR: fd%u couldn't seek\n", drive); floppy_prepare_motor_off(drive); return -2; } /*kprintf("FDD: fd%u: Seeked track succesfully\n", drive);*/ floppy_prepare_motor_off(drive); return 0; }
void floppy_reset(void) { int a; prepare_wait_irq(FLOPPY_IRQ); outportb((FLOPPY_FIRST + DIGITAL_OUTPUT_REGISTER), 0x00); /*disable controller*/ kwait(0, 1000 * 50); outportb((FLOPPY_FIRST + DIGITAL_OUTPUT_REGISTER), 0x0c); /*enable controller*/ kprintf("FDD: Reseted controller\n"); wait_irq(FLOPPY_IRQ); kprintf("FDD: Waited for it\n"); for(a = 0; a < 4; a++) { floppy_sense_interrupt(); } outportb(FLOPPY_FIRST + CONFIGURATION_CONTROL_REGISTER, 0); floppy_configure(); if (floppy_drives[0].type) { floppy_calibrate(0); } if (floppy_drives[1].type) { floppy_calibrate(1); } kprintf("FDD: Calibrated drives\n"); }
int init_floppy() { int drive = floppy_get_current_drive(); uint8_t drive_type = 0; uint8_t CCR; /* On vérifie qu'on a bien un controleur standard, sinon on affiche un warning */ if(floppy_get_version() != 0x90) kerr("WARNING: Floppy driver may not work with 0x%x controler.", floppy_get_version()); floppy_reset_irq(); // On fait le reset du controler + activation DMA/IRQ outb(0x00, FLOPPY_BASE + FLOPPY_DOR); outb(0x0C, FLOPPY_BASE + FLOPPY_DOR); floppy_wait_irq(); floppy_sense_interrupt(NULL,NULL); // On regle la vitesse de transfert en fonction du type de disquette drive_type = floppy_get_type(drive); switch(drive_type) { case 1: // 300 kbps (01) case 3: CCR = 0x01; break; case 2: // 500 kbps (00) case 4: CCR = 0x00; break; case 5: // 1 Mbps (11) CCR= 0x03; break; default: CCR = 0x00; // choix arbitraire btw break; } outb(CCR, FLOPPY_BASE + FLOPPY_CCR); /* Totalement hardcodé et moche à fortiori*/ floppy_write_command(SPECIFY); floppy_write_command(0xdf); /* steprate = 3ms, unload time = 240ms */ floppy_write_command(0x02); /* load time = 16ms, no-DMA = 0 */ /* *************************************** */ // On calibre le lecteur if(floppy_calibrate()) return -1; return 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; }