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; } }
void switch_tasks() { uint32_t eflags = disable_interrupts(); task_t *old_task = current_task(); task_t *current_candidate = old_task->next; task_t *first_candidate = current_candidate; task_t *selected = NULL; // Buscamos una tarea que este lista para ejecutarse. Si no hay ninguna, // hacemos halt hasta que ocurra una interrupcion. do { do { if (!(current_candidate->waiting)) { selected = current_candidate; break; } current_candidate = current_candidate->next; } while(current_candidate != first_candidate); if (selected == NULL) { outb(PIC1_DATA, (PIC_ALL_ENABLED & (~PIC_TIMER)) | PIC_TIMER); wait_for_interrupt(); outb(PIC1_DATA, PIC_ALL_ENABLED); } } while (selected == NULL); task_list = selected; switch_context(old_task, current_task()); restore_eflags(eflags); }
void floppy_move() { wait_for_FDC(); while(!floppy_motor); send_floppy_command(FLOPPY_RESET_CMD); send_floppy_data(FLOPPY_SELECT_A); floppy_interrupt_finished = 0; backup_eflags(); sti(); floppy_disable_other_interrupt(); while(!floppy_interrupt_finished); floppy_enable_other_interrupt(); restore_eflags(); floppy_check(); }
//------------------------------------------------------------------------------------------------------------------------------- // // 硬盘读写处理函数 // //------------------------------------------------------------------------------------------------------------------------------- void HardDiskRW(int RW, unsigned long sectors, void* buffer) { unsigned __eflag; int sector, head, cylinder; save_eflags(&__eflag); sector = sectors &0xff; cylinder = (sectors &0xffff00)>>8; head = (sectors &0xf000000)>>24; while(inb(HD_STATUS) & 0x80); io_wait(); outb(0,HD_CMD); outb(1,0x1f2); ///////////读写的扇区数.这个端口应该是:0X1F2,下面开始增加一 outb(sector,0x1f3); ////////开始扇区 outb(cylinder,0x1f4); ///////开始柱面 outb(cylinder>>8,0x1f5); ///////开始柱面高位 outb(0xE0|(0 <<4)|head,0x1f6); /////主磁盘 if (RW == READ) { ////read命令 outb(0x20,0x1F7); while(inb(HD_STATUS) & 0x80); insw(0x1F0, buffer, 256); } else if (RW == WRITE) { ////write命令 if (inb(HD_STATUS & 0x01)) { ConsoleWarning(" issue write_command command error !\n"); return; } outb(0x30,0x1F7); while((inb(HD_STATUS) & 0x08) == 0); //DRQ outsw(0x1F0, buffer, 256); } else { ConsoleWarning(" Panic:bad command:you only can read or write on harddisk!"); } restore_eflags(__eflag); return; }
void floppy_reset() { uint16_t sensei_data; write_port(FLOPPY_DOR_REG,0x00); write_port(FLOPPY_DOR_REG,FLOPPY_MOTOR_A|FLOPPY_DMA|FLOPPY_WORK|FLOPPY_SELECT_A); dor_status = FLOPPY_MOTOR_A|FLOPPY_DMA|FLOPPY_WORK|FLOPPY_SELECT_A; floppy_interrupt_finished = 0; backup_eflags(); sti(); floppy_disable_other_interrupt(); while(!floppy_interrupt_finished); floppy_enable_other_interrupt(); restore_eflags(); for (int i = 0; i<4; i++) { sensei_data = floppy_check(); } floppy_C = sensei_data&0xFF; st0 = sensei_data>>8; write_port(FLOPPY_DCR_REG,FLOPPY_500KBPS); floppy_set(); }
void floppy_seek(uint8_t C) { uint16_t sensei_data; wait_for_FDC(); while(!floppy_motor); send_floppy_command(FLOPPY_SEEK_CMD); send_floppy_data(FLOPPY_SELECT_A); send_floppy_data(C); floppy_C = C; floppy_interrupt_finished = 0; backup_eflags(); sti(); floppy_disable_other_interrupt(); while(!floppy_interrupt_finished); floppy_enable_other_interrupt(); restore_eflags(); sensei_data = floppy_check(); if((sensei_data&0xFF) != C) { show_char_now('E'); } if(sensei_data>>14) { show_char_now('e'); } }
/* * This actually diverts the Guest to running an interrupt handler, once an * interrupt has been identified by interrupt_pending(). */ void try_deliver_interrupt(struct lg_cpu *cpu, unsigned int irq, bool more) { struct desc_struct *idt; BUG_ON(irq >= LGUEST_IRQS); /* If they're halted, interrupts restart them. */ if (cpu->halted) { /* Re-enable interrupts. */ if (put_user(X86_EFLAGS_IF, &cpu->lg->lguest_data->irq_enabled)) kill_guest(cpu, "Re-enabling interrupts"); cpu->halted = 0; } else { /* Otherwise we check if they have interrupts disabled. */ u32 irq_enabled; if (get_user(irq_enabled, &cpu->lg->lguest_data->irq_enabled)) irq_enabled = 0; if (!irq_enabled) { /* Make sure they know an IRQ is pending. */ put_user(X86_EFLAGS_IF, &cpu->lg->lguest_data->irq_pending); return; } } /* * Look at the IDT entry the Guest gave us for this interrupt. The * first 32 (FIRST_EXTERNAL_VECTOR) entries are for traps, so we skip * over them. */ idt = &cpu->arch.idt[FIRST_EXTERNAL_VECTOR+irq]; /* If they don't have a handler (yet?), we just ignore it */ if (idt_present(idt->a, idt->b)) { /* OK, mark it no longer pending and deliver it. */ clear_bit(irq, cpu->irqs_pending); /* * They may be about to iret, where they asked us never to * deliver interrupts. In this case, we can emulate that iret * then immediately deliver the interrupt. This is basically * a noop: the iret would pop the interrupt frame and restore * eflags, and then we'd set it up again. So just restore the * eflags word and jump straight to the handler in this case. * * Denys Vlasenko points out that this isn't quite right: if * the iret was returning to userspace, then that interrupt * would reset the stack pointer (which the Guest told us * about via LHCALL_SET_STACK). But unless the Guest is being * *really* weird, that will be the same as the current stack * anyway. */ if (cpu->regs->eip == cpu->lg->noirq_iret) { restore_eflags(cpu); } else { /* * set_guest_interrupt() takes a flag to say whether * this interrupt pushes an error code onto the stack * as well: virtual interrupts never do. */ push_guest_interrupt_stack(cpu, false); } /* Actually make Guest cpu jump to handler. */ guest_run_interrupt(cpu, idt->a, idt->b); } /* * Every time we deliver an interrupt, we update the timestamp in the * Guest's lguest_data struct. It would be better for the Guest if we * did this more often, but it can actually be quite slow: doing it * here is a compromise which means at least it gets updated every * timer interrupt. */ write_timestamp(cpu); /* * If there are no other interrupts we want to deliver, clear * the pending flag. */ if (!more) put_user(0, &cpu->lg->lguest_data->irq_pending); }