void serial_init(void) { // Turn off the FIFO outb(COM1+COM_FCR, 0); // Set speed; requires DLAB latch outb(COM1+COM_LCR, COM_LCR_DLAB); outb(COM1+COM_DLL, (uint8_t) (115200 / 9600)); outb(COM1+COM_DLM, 0); // 8 data bits, 1 stop bit, parity off; turn off DLAB latch outb(COM1+COM_LCR, COM_LCR_WLEN8 & ~COM_LCR_DLAB); // No modem controls outb(COM1+COM_MCR, 0); // Enable rcv interrupts outb(COM1+COM_IER, COM_IER_RDI); // Clear any preexisting overrun indications and interrupts // Serial port doesn't exist if COM_LSR returns 0xFF serial_exists = (inb(COM1+COM_LSR) != 0xFF); (void) inb(COM1+COM_IIR); (void) inb(COM1+COM_RX); // Enable serial interrupts if (serial_exists) irq_setmask_8259A(irq_mask_8259A & ~(1<<4)); }
void kbd_init(void) { // Drain the kbd buffer so that Bochs generates interrupts. kbd_intr(); irq_setmask_8259A(irq_mask_8259A & ~(1<<1)); }
/* Initialize the 8259A interrupt controllers. */ void pic_init(void) { didinit = 1; // mask all interrupts outb(IO_PIC1+1, 0xFF); outb(IO_PIC2+1, 0xFF); // Set up master (8259A-1) // ICW1: 0001g0hi // g: 0 = edge triggering, 1 = level triggering // h: 0 = cascaded PICs, 1 = master only // i: 0 = no ICW4, 1 = ICW4 required outb(IO_PIC1, 0x11); // ICW2: Vector offset outb(IO_PIC1+1, IRQ_OFFSET); // ICW3: bit mask of IR lines connected to slave PICs (master PIC), // 3-bit No of IR line at which slave connects to master(slave PIC). outb(IO_PIC1+1, 1<<IRQ_SLAVE); // ICW4: 000nbmap // n: 1 = special fully nested mode // b: 1 = buffered mode // m: 0 = slave PIC, 1 = master PIC // (ignored when b is 0, as the master/slave role // can be hardwired). // a: 1 = Automatic EOI mode // p: 0 = MCS-80/85 mode, 1 = intel x86 mode outb(IO_PIC1+1, 0x3); // Set up slave (8259A-2) outb(IO_PIC2, 0x11); // ICW1 outb(IO_PIC2+1, IRQ_OFFSET + 8); // ICW2 outb(IO_PIC2+1, IRQ_SLAVE); // ICW3 // NB Automatic EOI mode doesn't tend to work on the slave. // Linux source code says it's "to be investigated". outb(IO_PIC2+1, 0x01); // ICW4 // OCW3: 0ef01prs // ef: 0x = NOP, 10 = clear specific mask, 11 = set specific mask // p: 0 = no polling, 1 = polling mode // rs: 0x = NOP, 10 = read IRR, 11 = read ISR outb(IO_PIC1, 0x68); /* clear specific mask */ outb(IO_PIC1, 0x0a); /* read IRR by default */ outb(IO_PIC2, 0x68); /* OCW3 */ outb(IO_PIC2, 0x0a); /* OCW3 */ if (irq_mask_8259A != 0xFFFF) irq_setmask_8259A(irq_mask_8259A); }
void kclock_init(void) { /* initialize 8253 clock to interrupt 100 times/sec */ outb(TIMER_MODE, TIMER_SEL0|TIMER_RATEGEN|TIMER_16BIT); outb(IO_TIMER1, TIMER_DIV(100) % 256); outb(IO_TIMER1, TIMER_DIV(100) / 256); printf(" Setup timer interrupts via 8259A\n"); irq_setmask_8259A (irq_mask_8259A & ~(1<<0)); printf(" unmasked timer interrupt\n"); }