PIC.cpp 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. #include "types.h"
  2. #include "i386.h"
  3. #include "IO.h"
  4. #include "PIC.h"
  5. #include "Assertions.h"
  6. // The slave 8259 is connected to the master's IRQ2 line.
  7. // This is really only to enhance clarity.
  8. #define SLAVE_INDEX 2
  9. #define PIC0_CTL 0x20
  10. #define PIC0_CMD 0x21
  11. #define PIC1_CTL 0xA0
  12. #define PIC1_CMD 0xA1
  13. #ifdef DEBUG_PIC
  14. static bool initialized;
  15. #endif
  16. namespace PIC {
  17. void disable(BYTE irq)
  18. {
  19. BYTE imr;
  20. if (irq & 8) {
  21. imr = IO::in8(PIC1_CMD);
  22. imr |= 1 << (irq - 8);
  23. IO::out8(PIC1_CMD, imr);
  24. } else {
  25. imr = IO::in8(PIC0_CMD);
  26. imr |= 1 << irq;
  27. IO::out8(PIC0_CMD, imr);
  28. }
  29. }
  30. void enable(BYTE irq)
  31. {
  32. BYTE imr;
  33. if (irq & 8) {
  34. imr = IO::in8(PIC1_CMD);
  35. imr &= ~(1 << (irq - 8));
  36. IO::out8(PIC1_CMD, imr);
  37. } else {
  38. imr = IO::in8(PIC0_CMD);
  39. imr &= ~(1 << irq);
  40. IO::out8(PIC0_CMD, imr);
  41. }
  42. }
  43. void eoi(BYTE irq)
  44. {
  45. if (irq & 8)
  46. IO::out8(PIC1_CTL, 0x20);
  47. IO::out8(PIC0_CTL, 0x20);
  48. }
  49. void initialize()
  50. {
  51. #ifdef DEBUG_PIC
  52. ASSERT(!initialized);
  53. #endif
  54. /* ICW1 (edge triggered mode, cascading controllers, expect ICW4) */
  55. IO::out8(PIC0_CTL, 0x11);
  56. IO::out8(PIC1_CTL, 0x11);
  57. /* ICW2 (upper 5 bits specify ISR indices, lower 3 idunno) */
  58. IO::out8(PIC0_CMD, IRQ_VECTOR_BASE);
  59. IO::out8(PIC1_CMD, IRQ_VECTOR_BASE + 0x08);
  60. /* ICW3 (configure master/slave relationship) */
  61. IO::out8(PIC0_CMD, 1 << SLAVE_INDEX);
  62. IO::out8(PIC1_CMD, SLAVE_INDEX);
  63. /* ICW4 (set x86 mode) */
  64. IO::out8(PIC0_CMD, 0x01);
  65. IO::out8(PIC1_CMD, 0x01 );
  66. // Mask -- start out with all IRQs disabled.
  67. IO::out8(PIC0_CMD, 0xff);
  68. IO::out8(PIC1_CMD, 0xff);
  69. // ...except IRQ2, since that's needed for the master to let through slave interrupts.
  70. enable(2);
  71. kprintf("PIC(i8259): cascading mode, vectors 0x%b-0x%b\n", IRQ_VECTOR_BASE, IRQ_VECTOR_BASE + 0x08);
  72. #ifdef DEBUG_PIC
  73. initialized = true;
  74. #endif
  75. }
  76. word getISR()
  77. {
  78. IO::out8(PIC0_CTL, 0x0b);
  79. IO::out8(PIC1_CTL, 0x0b);
  80. byte isr0 = IO::in8(PIC0_CTL);
  81. byte isr1 = IO::in8(PIC1_CTL);
  82. return (isr1 << 8) | isr0;
  83. }
  84. word get_irr()
  85. {
  86. IO::out8(PIC0_CTL, 0x0a);
  87. IO::out8(PIC1_CTL, 0x0a);
  88. byte irr0 = IO::in8(PIC0_CTL);
  89. byte irr1 = IO::in8(PIC1_CTL);
  90. return (irr1 << 8) | irr0;
  91. }
  92. }