《操作系统》的实验代码。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

86 lines
2.4 KiB

12 years ago
  1. #include <defs.h>
  2. #include <x86.h>
  3. #include <picirq.h>
  4. // I/O Addresses of the two programmable interrupt controllers
  5. #define IO_PIC1 0x20 // Master (IRQs 0-7)
  6. #define IO_PIC2 0xA0 // Slave (IRQs 8-15)
  7. #define IRQ_SLAVE 2 // IRQ at which slave connects to master
  8. // Current IRQ mask.
  9. // Initial IRQ mask has interrupt 2 enabled (for slave 8259A).
  10. static uint16_t irq_mask = 0xFFFF & ~(1 << IRQ_SLAVE);
  11. static bool did_init = 0;
  12. static void
  13. pic_setmask(uint16_t mask) {
  14. irq_mask = mask;
  15. if (did_init) {
  16. outb(IO_PIC1 + 1, mask);
  17. outb(IO_PIC2 + 1, mask >> 8);
  18. }
  19. }
  20. void
  21. pic_enable(unsigned int irq) {
  22. pic_setmask(irq_mask & ~(1 << irq));
  23. }
  24. /* pic_init - initialize the 8259A interrupt controllers */
  25. void
  26. pic_init(void) {
  27. did_init = 1;
  28. // mask all interrupts
  29. outb(IO_PIC1 + 1, 0xFF);
  30. outb(IO_PIC2 + 1, 0xFF);
  31. // Set up master (8259A-1)
  32. // ICW1: 0001g0hi
  33. // g: 0 = edge triggering, 1 = level triggering
  34. // h: 0 = cascaded PICs, 1 = master only
  35. // i: 0 = no ICW4, 1 = ICW4 required
  36. outb(IO_PIC1, 0x11);
  37. // ICW2: Vector offset
  38. outb(IO_PIC1 + 1, IRQ_OFFSET);
  39. // ICW3: (master PIC) bit mask of IR lines connected to slaves
  40. // (slave PIC) 3-bit # of slave's connection to master
  41. outb(IO_PIC1 + 1, 1 << IRQ_SLAVE);
  42. // ICW4: 000nbmap
  43. // n: 1 = special fully nested mode
  44. // b: 1 = buffered mode
  45. // m: 0 = slave PIC, 1 = master PIC
  46. // (ignored when b is 0, as the master/slave role
  47. // can be hardwired).
  48. // a: 1 = Automatic EOI mode
  49. // p: 0 = MCS-80/85 mode, 1 = intel x86 mode
  50. outb(IO_PIC1 + 1, 0x3);
  51. // Set up slave (8259A-2)
  52. outb(IO_PIC2, 0x11); // ICW1
  53. outb(IO_PIC2 + 1, IRQ_OFFSET + 8); // ICW2
  54. outb(IO_PIC2 + 1, IRQ_SLAVE); // ICW3
  55. // NB Automatic EOI mode doesn't tend to work on the slave.
  56. // Linux source code says it's "to be investigated".
  57. outb(IO_PIC2 + 1, 0x3); // ICW4
  58. // OCW3: 0ef01prs
  59. // ef: 0x = NOP, 10 = clear specific mask, 11 = set specific mask
  60. // p: 0 = no polling, 1 = polling mode
  61. // rs: 0x = NOP, 10 = read IRR, 11 = read ISR
  62. outb(IO_PIC1, 0x68); // clear specific mask
  63. outb(IO_PIC1, 0x0a); // read IRR by default
  64. outb(IO_PIC2, 0x68); // OCW3
  65. outb(IO_PIC2, 0x0a); // OCW3
  66. if (irq_mask != 0xFFFF) {
  67. pic_setmask(irq_mask);
  68. }
  69. }