From: Kevin O'Connor Date: Sat, 14 Jun 2008 19:56:16 +0000 (-0400) Subject: Cleanup handling of interrupt controller (PIC). X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=commitdiff_plain;h=f54c150090ff38a73ef64a5d20fdfa0d9c403972;p=seabios.git Cleanup handling of interrupt controller (PIC). Add new file (pic.h) with helpers for accessing the PIC. Move irq enabling code to the files that use those interrupts. Also, don't setup for floppy if floppy support not enabled. --- diff --git a/Makefile b/Makefile index b89170d..ca2a930 100644 --- a/Makefile +++ b/Makefile @@ -8,8 +8,9 @@ OUT=out/ # Source files -SRCBOTH=output.c util.c floppy.c ata.c kbd.c pci.c boot.c serial.c clock.c -SRC16=$(SRCBOTH) disk.c system.c mouse.c cdrom.c apm.c pcibios.c +SRCBOTH=output.c util.c floppy.c ata.c system.c mouse.c kbd.c pci.c boot.c \ + serial.c clock.c +SRC16=$(SRCBOTH) disk.c cdrom.c apm.c pcibios.c SRC32=$(SRCBOTH) post.c shadow.c rombios32.c post_menu.c memmap.c coreboot.c \ acpi.c pirtable.c TABLESRC=font.c cbt.c floppy_dbt.c diff --git a/src/ata.c b/src/ata.c index 998576c..4d3c660 100644 --- a/src/ata.c +++ b/src/ata.c @@ -10,6 +10,7 @@ #include "ioport.h" // inb #include "util.h" // dprintf #include "cmos.h" // inb_cmos +#include "pic.h" // unmask_pic2 #define TIMEOUT 0 #define BSY 1 @@ -947,4 +948,7 @@ hard_drive_setup() SET_BDA(disk_count, GET_EBDA(ata.hdcount)); SET_BDA(disk_control_byte, 0xc0); + + // Enable IRQ14 (handle_76) + unmask_pic2(PIC2_IRQ14); } diff --git a/src/clock.c b/src/clock.c index 5bf4642..605d436 100644 --- a/src/clock.c +++ b/src/clock.c @@ -9,6 +9,7 @@ #include "util.h" // debug_enter #include "disk.h" // floppy_tick #include "cmos.h" // inb_cmos +#include "pic.h" // unmask_pic1 #define DEBUGF1(fmt, args...) bprintf(0, fmt , ##args) #define DEBUGF(fmt, args...) @@ -55,6 +56,9 @@ timer_setup() ticks += (hours * 65543427) / 1000; SET_BDA(timer_counter, ticks); SET_BDA(timer_rollover, 0); + + // Enable IRQ0 (handle_08) + unmask_pic1(PIC1_IRQ0); } static void @@ -237,7 +241,7 @@ handle_1a06(struct bregs *regs) outb_cmos(regs->dh, CMOS_RTC_SECONDS_ALARM); outb_cmos(regs->cl, CMOS_RTC_MINUTES_ALARM); outb_cmos(regs->ch, CMOS_RTC_HOURS_ALARM); - outb(inb(PORT_PIC2_DATA) & ~PIC2_IRQ8, PORT_PIC2_DATA); // enable IRQ 8 + unmask_pic2(PIC2_IRQ8); // enable IRQ 8 // enable Status Reg B alarm bit, clear halt clock bit outb_cmos((val8 & ~RTC_B_SET) | RTC_B_AIE, CMOS_STATUS_B); set_success(regs); @@ -325,7 +329,7 @@ handle_08() irq_disable(); - eoi_master_pic(); + eoi_pic1(); } @@ -345,8 +349,7 @@ set_usertimer(u32 usecs, u16 seg, u16 offset) SET_BDA(user_wait_timeout, usecs); // Unmask IRQ8 so INT70 will get through. - u8 irqDisable = inb(PORT_PIC2_DATA); - outb(irqDisable & ~PIC2_IRQ8, PORT_PIC2_DATA); + unmask_pic2(PIC2_IRQ8); // Turn on the Periodic Interrupt timer u8 bRegister = inb_cmos(CMOS_STATUS_B); outb_cmos(bRegister | RTC_B_PIE, CMOS_STATUS_B); @@ -489,5 +492,5 @@ handle_70() } done: - eoi_both_pics(); + eoi_pic2(); } diff --git a/src/disk.c b/src/disk.c index c45d6ad..e6b82b0 100644 --- a/src/disk.c +++ b/src/disk.c @@ -10,6 +10,7 @@ #include "config.h" // CONFIG_* #include "util.h" // debug_enter #include "ata.h" // ATA_* +#include "pic.h" // eoi_pic2 #define DEBUGF1(fmt, args...) bprintf(0, fmt , ##args) #define DEBUGF(fmt, args...) @@ -678,5 +679,5 @@ handle_76() { debug_isr(DEBUG_ISR_76); SET_BDA(disk_interrupt_flag, 0xff); - eoi_both_pics(); + eoi_pic2(); } diff --git a/src/floppy.c b/src/floppy.c index e0b46c2..efe9592 100644 --- a/src/floppy.c +++ b/src/floppy.c @@ -11,6 +11,7 @@ #include "biosvar.h" // struct bregs #include "util.h" // irq_disable #include "cmos.h" // inb_cmos +#include "pic.h" // unmask_pic1 #define DEBUGF1(fmt, args...) bprintf(0, fmt , ##args) #define DEBUGF(fmt, args...) @@ -43,6 +44,8 @@ struct floppy_ext_dbt_s diskette_param_table2 VISIBLE16 = { void floppy_drive_setup() { + if (! CONFIG_FLOPPY_SUPPORT) + return; dprintf(3, "init floppy drives\n"); u8 type = inb_cmos(CMOS_FLOPPY_DRIVE_TYPE); u8 out = 0; @@ -67,6 +70,9 @@ floppy_drive_setup() SETBITS_BDA(equipment_list_flags, 0x41); outb(0x02, PORT_DMA1_MASK_REG); + + // Enable IRQ6 (handle_0e) + unmask_pic1(PIC1_IRQ6); } static inline void @@ -753,7 +759,7 @@ handle_0e() inb(PORT_FD_DATA); } while ((inb(PORT_FD_STATUS) & 0xc0) == 0xc0); } - eoi_master_pic(); + eoi_pic1(); // diskette interrupt has occurred SETBITS_BDA(floppy_recalibration_status, FRS_TIMEOUT); } diff --git a/src/ioport.h b/src/ioport.h index a51d713..2ac8602 100644 --- a/src/ioport.h +++ b/src/ioport.h @@ -14,7 +14,7 @@ #define PORT_DMA1_MODE_REG 0x000b #define PORT_DMA1_CLEAR_FF_REG 0x000c #define PORT_DMA1_MASTER_CLEAR 0x000d -#define PORT_PIC1 0x0020 +#define PORT_PIC1_CMD 0x0020 #define PORT_PIC1_DATA 0x0021 #define PORT_PIT_COUNTER0 0x0040 #define PORT_PIT_COUNTER1 0x0041 @@ -28,7 +28,7 @@ #define PORT_DIAG 0x0080 #define PORT_DMA_PAGE_2 0x0081 #define PORT_A20 0x0092 -#define PORT_PIC2 0x00a0 +#define PORT_PIC2_CMD 0x00a0 #define PORT_PIC2_DATA 0x00a1 #define PORT_DMA2_MASK_REG 0x00d4 #define PORT_DMA2_MODE_REG 0x00d6 @@ -44,12 +44,6 @@ #define PORT_BIOS_DEBUG 0x0403 #define PORT_BIOS_APM 0x8900 -// PORT_PIC1 bitdefs -#define PIC1_IRQ5 (1<<5) -// PORT_PIC2 bitdefs -#define PIC2_IRQ8 (1<<0) -#define PIC2_IRQ13 (1<<5) - // PORT_KBD_CTRLB bitdefs #define KBD_REFRESH (1<<4) diff --git a/src/kbd.c b/src/kbd.c index fe2a77d..4304c0d 100644 --- a/src/kbd.c +++ b/src/kbd.c @@ -8,6 +8,7 @@ #include "biosvar.h" // struct bregs #include "util.h" // debug_enter #include "config.h" // CONFIG_* +#include "pic.h" // eoi_pic1 //-------------------------------------------------------------------------- // keyboard_panic @@ -160,6 +161,9 @@ kbd_setup() , x + FIELD_SIZEOF(struct bios_data_area_s, kbd_buf)); keyboard_init(); + + // Enable IRQ1 (handle_09) + unmask_pic1(PIC1_IRQ1); } static u8 @@ -705,8 +709,8 @@ handle_09() // disable keyboard outb(0xad, PORT_PS2_STATUS); - outb(0x0b, PORT_PIC1); - if ((inb(PORT_PIC1) & 0x02) == 0) + // Make sure there really is a keyboard irq pending. + if (! (get_pic1_isr() & PIC1_IRQ1)) goto done; // read key from keyboard controller @@ -727,7 +731,7 @@ handle_09() process_key(key); irq_disable(); - eoi_master_pic(); + eoi_pic1(); done: // enable keyboard diff --git a/src/mouse.c b/src/mouse.c index 23e17de..8f6775f 100644 --- a/src/mouse.c +++ b/src/mouse.c @@ -7,12 +7,25 @@ #include "biosvar.h" // struct bregs #include "util.h" // debug_isr +#include "pic.h" // unmask_pic2 #define DEBUGF1(fmt, args...) bprintf(0, fmt , ##args) #define DEBUGF(fmt, args...) static char panic_msg_keyb_buffer_full[] = "%s: keyboard input buffer full\n"; +void +mouse_setup() +{ + if (! CONFIG_PS2_MOUSE) + return; + dprintf(3, "init mouse\n"); + // pointing device installed + SETBITS_BDA(equipment_list_flags, 0x04); + // Enable IRQ12 (handle_74) + unmask_pic2(PIC2_IRQ12); +} + static void set_kbd_command_byte(u8 command_byte) { @@ -421,5 +434,5 @@ handle_74() int74_function(); irq_disable(); - eoi_both_pics(); + eoi_pic2(); } diff --git a/src/pic.h b/src/pic.h new file mode 100644 index 0000000..0eb70ee --- /dev/null +++ b/src/pic.h @@ -0,0 +1,77 @@ +// Helpers for working with i8259 interrupt controller. +// +// Copyright (C) 2008 Kevin O'Connor +// Copyright (C) 2002 MandrakeSoft S.A. +// +// This file may be distributed under the terms of the GNU GPLv3 license. + +#include "ioport.h" // PORT_PIC* +#include "util.h" // dprintf + +// PORT_PIC1 bitdefs +#define PIC1_IRQ0 (1<<0) +#define PIC1_IRQ1 (1<<1) +#define PIC1_IRQ2 (1<<2) +#define PIC1_IRQ5 (1<<5) +#define PIC1_IRQ6 (1<<6) +// PORT_PIC2 bitdefs +#define PIC2_IRQ8 (1<<0) +#define PIC2_IRQ12 (1<<4) +#define PIC2_IRQ13 (1<<5) +#define PIC2_IRQ14 (1<<6) + +static inline void +eoi_pic1() +{ + // Send eoi (select OCW2 + eoi) + outb(0x20, PORT_PIC1_CMD); +} + +static inline void +eoi_pic2() +{ + // Send eoi (select OCW2 + eoi) + outb(0x20, PORT_PIC2_CMD); + eoi_pic1(); +} + +static inline void +unmask_pic1(u8 irq) +{ + outb(inb(PORT_PIC1_DATA) & ~irq, PORT_PIC1_DATA); +} + +static inline void +unmask_pic2(u8 irq) +{ + outb(inb(PORT_PIC2_DATA) & ~irq, PORT_PIC2_DATA); +} + +static inline u8 +get_pic1_isr() +{ + // 0x0b == select OCW1 + read ISR + outb(0x0b, PORT_PIC1_CMD); + return inb(PORT_PIC1_CMD); +} + +static inline void +pic_setup() +{ + dprintf(3, "init pic\n"); + // Send ICW1 (select OCW1 + will send ICW4) + outb(0x11, PORT_PIC1_CMD); + outb(0x11, PORT_PIC2_CMD); + // Send ICW2 (base irqs: 0x08-0x0f for irq0-7, 0x70-0x78 for irq8-15) + outb(0x08, PORT_PIC1_DATA); + outb(0x70, PORT_PIC2_DATA); + // Send ICW3 (cascaded pic ids) + outb(0x04, PORT_PIC1_DATA); + outb(0x02, PORT_PIC2_DATA); + // Send ICW4 (enable 8086 mode) + outb(0x01, PORT_PIC1_DATA); + outb(0x01, PORT_PIC2_DATA); + // Mask all irqs (except cascaded PIC2 irq) + outb(~PIC1_IRQ2, PORT_PIC1_DATA); + outb(~0, PORT_PIC2_DATA); +} diff --git a/src/post.c b/src/post.c index afbd360..766e898 100644 --- a/src/post.c +++ b/src/post.c @@ -15,6 +15,7 @@ #include "kbd.h" // kbd_setup #include "disk.h" // floppy_drive_setup #include "memmap.h" // add_e820 +#include "pic.h" // pic_setup #define bda ((struct bios_data_area_s *)MAKE_FARPTR(SEG_BDA, 0)) #define ebda ((struct extended_bios_data_area_s *)MAKE_FARPTR(SEG_EBDA, 0)) @@ -25,42 +26,39 @@ init_bda() dprintf(3, "init bda\n"); memset(bda, 0, sizeof(*bda)); + SET_BDA(mem_size_kb, BASE_MEM_IN_K); + int i; for (i=0; i<256; i++) { SET_BDA(ivecs[i].seg, SEG_BIOS); SET_BDA(ivecs[i].offset, OFFSET_dummy_iret_handler); } - SET_BDA(mem_size_kb, BASE_MEM_IN_K); - - // Set BDA Equipment Word - 0x06 = FPU enable, mouse installed - SET_BDA(equipment_list_flags, 0x06); - - // set vector 0x79 to zero - // this is used by 'gardian angel' protection system - SET_BDA(ivecs[0x79].seg, 0); - SET_BDA(ivecs[0x79].offset, 0); - - SET_BDA(ivecs[0x40].offset, OFFSET_entry_40); + SET_BDA(ivecs[0x08].offset, OFFSET_entry_08); + SET_BDA(ivecs[0x09].offset, OFFSET_entry_09); SET_BDA(ivecs[0x0e].offset, OFFSET_entry_0e); + SET_BDA(ivecs[0x10].offset, OFFSET_entry_10); + SET_BDA(ivecs[0x11].offset, OFFSET_entry_11); + SET_BDA(ivecs[0x12].offset, OFFSET_entry_12); SET_BDA(ivecs[0x13].offset, OFFSET_entry_13); - SET_BDA(ivecs[0x76].offset, OFFSET_entry_76); + SET_BDA(ivecs[0x14].offset, OFFSET_entry_14); + SET_BDA(ivecs[0x15].offset, OFFSET_entry_15); + SET_BDA(ivecs[0x16].offset, OFFSET_entry_16); SET_BDA(ivecs[0x17].offset, OFFSET_entry_17); SET_BDA(ivecs[0x18].offset, OFFSET_entry_18); SET_BDA(ivecs[0x19].offset, OFFSET_entry_19); - SET_BDA(ivecs[0x1c].offset, OFFSET_entry_1c); - SET_BDA(ivecs[0x12].offset, OFFSET_entry_12); - SET_BDA(ivecs[0x11].offset, OFFSET_entry_11); - SET_BDA(ivecs[0x15].offset, OFFSET_entry_15); - SET_BDA(ivecs[0x08].offset, OFFSET_entry_08); - SET_BDA(ivecs[0x09].offset, OFFSET_entry_09); - SET_BDA(ivecs[0x16].offset, OFFSET_entry_16); - SET_BDA(ivecs[0x14].offset, OFFSET_entry_14); SET_BDA(ivecs[0x1a].offset, OFFSET_entry_1a); + SET_BDA(ivecs[0x1c].offset, OFFSET_entry_1c); + SET_BDA(ivecs[0x40].offset, OFFSET_entry_40); SET_BDA(ivecs[0x70].offset, OFFSET_entry_70); SET_BDA(ivecs[0x74].offset, OFFSET_entry_74); SET_BDA(ivecs[0x75].offset, OFFSET_entry_75); - SET_BDA(ivecs[0x10].offset, OFFSET_entry_10); + SET_BDA(ivecs[0x76].offset, OFFSET_entry_76); + + // set vector 0x79 to zero + // this is used by 'gardian angel' protection system + SET_BDA(ivecs[0x79].seg, 0); + SET_BDA(ivecs[0x79].offset, 0); SET_BDA(ivecs[0x1E].offset, OFFSET_diskette_param_table2); } @@ -109,25 +107,6 @@ ram_probe(void) dprintf(1, "ram_size=0x%08x\n", GET_EBDA(ram_size)); } -static void -pic_setup() -{ - dprintf(3, "init pic\n"); - outb(0x11, PORT_PIC1); - outb(0x11, PORT_PIC2); - outb(0x08, PORT_PIC1_DATA); - outb(0x70, PORT_PIC2_DATA); - outb(0x04, PORT_PIC1_DATA); - outb(0x02, PORT_PIC2_DATA); - outb(0x01, PORT_PIC1_DATA); - outb(0x01, PORT_PIC2_DATA); - outb(0xb8, PORT_PIC1_DATA); - if (CONFIG_PS2_MOUSE) - outb(0x8f, PORT_PIC2_DATA); - else - outb(0x9f, PORT_PIC2_DATA); -} - static void init_boot_vectors() { @@ -232,11 +211,13 @@ post() init_bda(); init_ebda(); + pic_setup(); timer_setup(); kbd_setup(); lpt_setup(); serial_setup(); - pic_setup(); + mouse_setup(); + mathcp_setup(); memmap_setup(); @@ -301,7 +282,7 @@ check_restart_status() // XXX - this is supposed to jump without changing any memory - // but the stack has been altered by the time the code gets here. - eoi_both_pics(); + eoi_pic2(); struct bregs br; memset(&br, 0, sizeof(br)); br.cs = GET_BDA(jump_cs_ip) >> 16; diff --git a/src/system.c b/src/system.c index 0941565..e73fe5c 100644 --- a/src/system.c +++ b/src/system.c @@ -9,6 +9,7 @@ #include "biosvar.h" // BIOS_CONFIG_TABLE #include "ioport.h" // inb #include "memmap.h" // E820_RAM +#include "pic.h" // eoi_pic2 // Use PS2 System Control port A to set A20 enable static inline u8 @@ -368,6 +369,16 @@ handle_nmi() BX_PANIC("NMI Handler called\n"); } +void +mathcp_setup() +{ + dprintf(3, "math cp init\n"); + // 80x87 coprocessor installed + SETBITS_BDA(equipment_list_flags, 0x02); + // Enable IRQ13 (handle_75) + unmask_pic2(PIC2_IRQ13); +} + // INT 75 - IRQ13 - MATH COPROCESSOR EXCEPTION void VISIBLE16 handle_75() @@ -377,7 +388,7 @@ handle_75() // clear irq13 outb(0, PORT_MATH_CLEAR); // clear interrupt - eoi_both_pics(); + eoi_pic2(); // legacy nmi call struct bregs br; memset(&br, 0, sizeof(br)); diff --git a/src/util.h b/src/util.h index 8a71569..ee42f6c 100644 --- a/src/util.h +++ b/src/util.h @@ -56,19 +56,6 @@ void *memset(void *s, int c, size_t n); void *memcpy(void *d1, const void *s1, size_t len); void *memmove(void *d, const void *s, size_t len); -static inline void -eoi_master_pic() -{ - outb(PIC1_IRQ5, PORT_PIC1); -} - -static inline void -eoi_both_pics() -{ - outb(PIC2_IRQ13, PORT_PIC2); - eoi_master_pic(); -} - // Call a function with a specified register state. Note that on // return, the interrupt enable/disable flag may be altered. static inline @@ -170,6 +157,12 @@ void __set_code_fail(const char *fname, struct bregs *regs, u8 code); // kbd.c void handle_15c2(struct bregs *regs); +// mouse.c +void mouse_setup(); + +// system.c +void mathcp_setup(); + // serial.c void serial_setup(); void lpt_setup();