فهرست منبع

Correct handling of lowering irqs

copy 7 سال پیش
والد
کامیت
a7a8c271cb
8فایلهای تغییر یافته به همراه48 افزوده شده و 39 حذف شده
  1. 0 6
      src/cpu.js
  2. 1 0
      src/floppy.js
  3. 5 0
      src/ne2k.js
  4. 28 10
      src/pic.js
  5. 4 0
      src/pit.js
  6. 5 14
      src/ps2.js
  7. 4 9
      src/rtc.js
  8. 1 0
      src/virtio.js

+ 0 - 6
src/cpu.js

@@ -3080,12 +3080,6 @@ CPU.prototype.device_raise_irq = function(i)
     {
         this.devices.apic.set_irq(i);
     }
-
-    // XXX: This should be implemented by the devices themselves
-    if(i !== 14 && i !== 15)
-    {
-        this.device_lower_irq(i);
-    }
 };
 
 CPU.prototype.device_lower_irq = function(i)

+ 1 - 0
src/floppy.js

@@ -196,6 +196,7 @@ FloppyController.prototype.port3F5_read = function()
     if(this.response_index < this.response_length)
     {
         dbg_log("3F5 read: " + this.response_data[this.response_index], LOG_DISK);
+        this.cpu.device_lower_irq(6);
         return this.response_data[this.response_index++];
     }
     else

+ 5 - 0
src/ne2k.js

@@ -275,6 +275,7 @@ function Ne2k(cpu, bus)
             // acknoledge interrupts where bit is set
             dbg_log("Write isr: " + h(data_byte, 2), LOG_NET);
             this.isr &= ~data_byte
+            this.update_irq();
         }
         else
         {
@@ -544,6 +545,10 @@ Ne2k.prototype.update_irq = function()
     {
         this.cpu.device_raise_irq(this.irq);
     }
+    else
+    {
+        this.cpu.device_lower_irq(this.irq);
+    }
 };
 
 Ne2k.prototype.data_port_write = function(data_byte)

+ 28 - 10
src/pic.js

@@ -100,13 +100,14 @@ function PIC(cpu, master)
             var irq_number = v86util.int_log2_byte(irq_mask);
             dbg_assert(irq_mask === (1 << irq_number));
 
-            this.irr &= ~irq_mask;
+            this.irr &= ~irq_mask; // not in level mode
 
             if(irq_number === 2)
             {
                 // this should always return true
+                this.irq_value &= ~2;
                 var did = this.slave.check_irqs();
-                dbg_log("Slave had irq when master irq number was 2: " + did, LOG_PIC);
+                if(!did) dbg_log("Slave had irq when master irq number was 2", LOG_PIC);
                 return did;
             }
 
@@ -152,7 +153,7 @@ function PIC(cpu, master)
             var irq_number = v86util.int_log2_byte(irq_mask);
             dbg_assert(irq_mask === (1 << irq_number));
 
-            this.irr &= ~irq_mask;
+            this.irr &= ~irq_mask; // not in level mode
 
             dbg_log("slave > handling irq " + irq_number, LOG_PIC);
             this.cpu.pic_call_irq(this.irq_map | irq_number);
@@ -368,10 +369,13 @@ function PIC(cpu, master)
             }
 
             var irq_mask = 1 << irq_number;
-            this.irr |= irq_mask & ~this.irq_value;
-            this.irq_value |= irq_mask;
+            if((this.irq_value & irq_mask) === 0)
+            {
+                this.irr |= irq_mask & ~this.irq_value;
+                this.irq_value |= irq_mask;
 
-            this.cpu.handle_irqs();
+                this.cpu.handle_irqs();
+            }
         };
 
         this.clear_irq = function(irq_number)
@@ -388,7 +392,12 @@ function PIC(cpu, master)
                 irq_number = 2;
             }
 
-            this.irq_value &= ~(1 << irq_number);
+            var irq_mask = 1 << irq_number;
+            if(this.irq_value & irq_mask)
+            {
+                this.irq_value &= ~irq_mask
+                this.irr &= ~irq_mask;
+            }
         };
     }
     else
@@ -402,18 +411,27 @@ function PIC(cpu, master)
             }
 
             var irq_mask = 1 << irq_number;
-            this.irr |= irq_mask & ~this.irq_value;
-            this.irq_value |= irq_mask;
+            if((this.irq_value & irq_mask) === 0)
+            {
+                this.irr |= irq_mask;
+                this.irq_value |= irq_mask;
+            }
         };
 
         this.clear_irq = function(irq_number)
         {
+            dbg_assert(irq_number >= 0 && irq_number < 8);
             if(PIC_LOG_VERBOSE)
             {
                 dbg_log("slave > clear irq " + irq_number, LOG_PIC);
             }
 
-            this.irq_value &= ~(1 << irq_number);
+            var irq_mask = 1 << irq_number;
+            if(this.irq_value & irq_mask)
+            {
+                this.irq_value &= ~irq_mask;
+                this.irr &= ~irq_mask;
+            }
         };
     }
 

+ 4 - 0
src/pit.js

@@ -108,6 +108,10 @@ PIT.prototype.timer = function(now, no_irq)
                 this.counter_enabled[0] = 0;
             }
         }
+        else
+        {
+            this.cpu.device_lower_irq(0);
+        }
     }
     time_to_next_interrupt = 0;
 

+ 5 - 14
src/ps2.js

@@ -298,19 +298,6 @@ PS2.prototype.apply_scaling2 = function(n)
     }
 }
 
-PS2.prototype.destroy = function()
-{
-    //if(this.have_keyboard)
-    //{
-    //    this.keyboard.destroy();
-    //}
-
-    //if(this.have_mouse)
-    //{
-    //    this.mouse.destroy();
-    //}
-};
-
 PS2.prototype.next_byte_is_aux = function()
 {
     return this.mouse_buffer.length && !this.kbd_buffer.length;
@@ -329,6 +316,9 @@ PS2.prototype.port60_read = function()
 
     var do_mouse_buffer = this.next_byte_is_aux();
 
+    this.cpu.device_lower_irq(1);
+    this.cpu.device_lower_irq(12);
+
     if(do_mouse_buffer)
     {
         this.last_port60_byte = this.mouse_buffer.shift();
@@ -379,11 +369,12 @@ PS2.prototype.port60_write = function(write_byte)
 
     if(this.read_command_register)
     {
-        this.kbd_irq();
         this.command_register = write_byte;
         this.read_command_register = false;
+
         // not sure, causes "spurious ack" in Linux
         //this.kbd_buffer.push(0xFA);
+        //this.kbd_irq();
 
         dbg_log("Keyboard command register = " + h(this.command_register), LOG_PS2);
     }

+ 4 - 9
src/rtc.js

@@ -61,8 +61,6 @@ function RTC(cpu)
     // used for periodic interrupt
     this.next_interrupt = 0;
 
-    this.cmos_c_was_read = true;
-
     this.periodic_interrupt = false;
 
     // corresponds to default value for cmos_a
@@ -93,7 +91,7 @@ RTC.prototype.get_state = function()
     state[2] = this.rtc_time;
     state[3] = this.last_update;
     state[4] = this.next_interrupt;
-    state[5] = this.cmos_c_was_read;
+
     state[6] = this.periodic_interrupt;
     state[7] = this.periodic_interrupt_time;
     state[8] = this.cmos_a;
@@ -111,7 +109,7 @@ RTC.prototype.set_state = function(state)
     this.rtc_time = state[2];
     this.last_update = state[3];
     this.next_interrupt = state[4];
-    this.cmos_c_was_read = state[5];
+
     this.periodic_interrupt = state[6];
     this.periodic_interrupt_time = state[7];
     this.cmos_a = state[8];
@@ -126,9 +124,8 @@ RTC.prototype.timer = function(time, legacy_mode)
     this.rtc_time += time - this.last_update;
     this.last_update = time;
 
-    if(this.periodic_interrupt && this.cmos_c_was_read && this.next_interrupt < time)
+    if(this.periodic_interrupt && this.next_interrupt < time)
     {
-        this.cmos_c_was_read = false;
         this.cpu.device_raise_irq(8);
         this.cmos_c |= 1 << 6 | 1 << 7;
 
@@ -207,13 +204,11 @@ RTC.prototype.cmos_port_read = function()
             return this.cmos_b;
 
         case CMOS_STATUS_C:
-            this.cmos_c_was_read = true;
-
-            // TODO:
             // It is important to know that upon a IRQ 8, Status Register C
             // will contain a bitmask telling which interrupt happened.
             // What is important is that if register C is not read after an
             // IRQ 8, then the interrupt will not happen again.
+            this.cpu.device_lower_irq(8);
 
             dbg_log("cmos reg C read", LOG_RTC);
             // Missing IRQF flag

+ 1 - 0
src/virtio.js

@@ -123,6 +123,7 @@ function VirtIO(cpu, bus, filesystem)
         // reading resets the isr
         var isr = this.isr;
         this.isr = 0;
+        this.cpu.device_lower_irq(this.irq);
         return isr;
     });