static BOOL do_harddisk_read() { #if 0 static rgb_t color = { 0xff, 0xff, 0x66 }; static s32 x = 10; static s32 y = 10; draw_dec(hd_sect_to_read, x, y, color); x += 36; if (x >= 1000) { x = 0; y += 16; } #endif /* read from harddisk */ io_insl(HD_PORT_DATA, hd_read_buffer, 1 << 7); hd_read_buffer += 512; hd_sect_to_read--; /* 设置EOI,通知中断结束,以接收下一次中断 */ io_outb(0x20, 0x20); io_outb(0x20, 0xa0); return TRUE; }
/* * Write to an ATA register */ static void ata_reg_write(ata_driver_t *drv, unsigned char channel, unsigned char reg, unsigned char data) { // High LBA flag if (reg > 0x07 && reg < 0x0C) { ata_reg_write(drv, channel, ATA_REG_CONTROL, 0x80 | drv->channels[channel].nIEN); } if (reg < 0x08) { io_outb(drv->channels[channel].base + reg - 0x00, data); } else if (reg < 0x0C) { io_outb(drv->channels[channel].base + reg - 0x06, data); } else if (reg < 0x0E) { io_outb(drv->channels[channel].ctrl + reg - 0x0A, data); } else if (reg < 0x16) { io_outb(drv->channels[channel].bmide + reg - 0x0E, data); } // Reset high LBA flag if (reg > 0x07 && reg < 0x0C) { ata_reg_write(drv, channel, ATA_REG_CONTROL, drv->channels[channel].nIEN); } }
static unsigned int videointerface_wcolormap(unsigned int offset, void *buffer, unsigned int count) { char *c = buffer; unsigned int i; if (count > VGA_COLORMAP_LIMIT) count = VGA_COLORMAP_LIMIT; if (offset > count) return 0; for (i = offset; i < count * 3; i += 3) { io_outb(VGA_REGISTER_DACWINDEX, i / 3); io_outb(VGA_REGISTER_DACDATA, c[i + 0]); io_outb(VGA_REGISTER_DACDATA, c[i + 1]); io_outb(VGA_REGISTER_DACDATA, c[i + 2]); } return i - offset; }
static unsigned int videointerface_writecolormap(struct system_node *self, struct system_node *current, struct service_state *state, void *buffer, unsigned int count, unsigned int offset) { char *c = buffer; unsigned int i; if (count > VGA_COLORMAP_LIMIT) count = VGA_COLORMAP_LIMIT; if (offset > count) return 0; for (i = offset; i < count * 3; i += 3) { io_outb(VGA_REGISTER_DACWINDEX, i / 3); io_outb(VGA_REGISTER_DACDATA, c[i + 0]); io_outb(VGA_REGISTER_DACDATA, c[i + 1]); io_outb(VGA_REGISTER_DACDATA, c[i + 2]); } return i - offset; }
MouseDriver::MouseDriver() : Driver("Mouse", "ps") { uint8_t status; Wait(1); io_outb(0x64, 0xA8); Wait(1); io_outb(0x64, 0x20); Wait(0); status = (io_inb(0x60) | 2); Wait(1); io_outb(0x64, 0x60); Wait(1); io_outb(0x60, status); // Valori di default MouseWrite(0xF6); MouseRead(); // Abilita lo sacmbio dati MouseWrite(0xF4); MouseRead(); // Scaling 1:1 MouseWrite(0xE6); MouseRead(); // Imposta l'handler setHandler(MouseDriver::IRQ, &MouseCallback); }
/** * Disables the IRQ by masking all interrupts. */ void irq_pic_disable() { // Disable PIC2 io_outb(IO_PIC2_DATA, 0xFF); // Disable PIC1 io_outb(IO_PIC1_DATA, 0xFF); }
void console_write(char *string) { unsigned int curchar, vidmem_off, i; io_outb(0x3d4, 0x0e); /* Get cursor Y position */ vidmem_off = io_inb(0x3d5); vidmem_off <<= 8; io_outb(0x3d4, 0x0f); /* And add cursor X position */ vidmem_off += io_inb(0x3d5); vidmem_off <<= 1; while((curchar=*string++)) /* Loop through the string */ { switch(curchar) /* Is it a special character ? */ { case '\n': /* Newline found */ vidmem_off = (vidmem_off/160)*160 + 160; break; case '\r': /* Carriage return found */ vidmem_off = (vidmem_off/160)*160; break; case '\t': vidmem_off += 8; break; case 8:/* Delete */ vidmem_off-=2; VIDEO_MEMORY[vidmem_off] = 0x20; break; default: /* Normal character */ VIDEO_MEMORY[vidmem_off++] = curchar; VIDEO_MEMORY[vidmem_off++] = 0x07; break; } if(vidmem_off >= 160*25) /* Are we off-screen ? */ { for(i = 0; i < 160*24; i++) /* Scroll the screen up */ { VIDEO_MEMORY[i] = VIDEO_MEMORY[i+160]; } for(i = 0; i < 80; i++) /* Empty the bottom row */ { VIDEO_MEMORY[(160*24)+(i*2)] = 0x20; VIDEO_MEMORY[(160*24)+(i*2)+1] = 0x07; } vidmem_off -= 160; /* We're on the bottom row */ } } vidmem_off >>= 1; /* Set the new cursor position */ io_outb(0x3d4, 0x0f); io_outb(0x3d5, vidmem_off & 0x0ff); io_outw(0x3d4, 0x0e); io_outb(0x3d5, vidmem_off >> 8); }/* console_write */
void irq_handler(const struct cpu_state* regs) { if (regs->interrupt >= 40) { io_outb(PIC_SLAVE_CMND, PIC_RESET); } io_outb(PIC_MASTER_CMND, PIC_RESET); call_interrupt_handler(regs); }
void MouseWrite(uint8_t a_write) { Wait(1); io_outb(0x64, 0xD4); Wait(1); io_outb(0x60, a_write); }
/** * Signals an EOI (end of interrupt) for the IRQ with the given index. * * @param index The index of the IRQ to signal an EOI for. */ void irq_pic_eoi(uint8_t index) { // PIC2? if (index > 7) io_outb(IO_PIC2_COMMAND, 0x20); // PIC1 io_outb(IO_PIC1_COMMAND, 0x20); }
void kkeyb_update_leds(uint8_t status) { while((io_inb(0x64)&2)!=0){} io_outb(0x60,0xED); while((io_inb(0x64)&2)!=0){} io_outb(0x60,status); }
void setleds() { io_outb(0x60, 0xED); while(io_inb(0x64) & 2) /* wait. */; io_outb(0x60, led_status); while(io_inb(0x64) & 2) /* wait. */; }
/** * Aggiorna lo stato dei led della tastiera */ void keyboard_update_leds(uint8_t status) { uint8_t tmp; while((io_inb(0x64)&2)!=0){} io_outb(0x60,0xED); while((io_inb(0x64)&2)!=0){} io_outb(0x60,status); }
/** * Masks the IRQ with the given index. * * @param index The index of the IRQ to mask. */ void irq_pic_mask(uint8_t index) { // IRQ 2 cannot be masked if (UNLIKELY(2 == index)) return; // PIC 1 or PIC 2? if (index > 7 && index <= 15) io_outb(IO_PIC2_DATA, io_inb(IO_PIC2_DATA) | (1 << (index - 8))); else if (index <= 7) io_outb(IO_PIC1_DATA, io_inb(IO_PIC1_DATA) | (1 << index)); }
static void driver_reset(unsigned int id) { io = platform_getbase(id); io_outb(io + REGISTERCOMMAND, COMMANDCHANNEL0 | COMMANDBOTH | COMMANDMODE3 | COMMANDBINARY); io_outb(io + REGISTERCHANNEL0, divisor); io_outb(io + REGISTERCHANNEL0, divisor >> 8); }
/** * Unmasks the IRQ with the given index. * * @param index The index of the IRQ to unmask. */ void irq_pic_unmask(uint8_t index) { // IRQ 2 is always unmasked if (2 == index) return; // PIC 1 or PIC 2? if (index > 7 && index <= 15) io_outb(IO_PIC2_DATA, io_inb(IO_PIC2_DATA) & ~(1 << (index - 8))); else if (index <= 7) io_outb(IO_PIC1_DATA, io_inb(IO_PIC1_DATA) & ~(1 << index)); }
void _dma_io(u8_t DMA_channel, unsigned char page, unsigned int offset, unsigned int length, u8_t mode) { /* Don't let anyone else mess up what we're doing. */ asm_disable_interrupt(); /* Set up the DMA channel so we can use it. This tells the DMA */ /* that we're going to be using this channel. (It's masked) */ io_outb(MaskReg[DMA_channel], 0x04 | DMA_channel); /* Clear any data transfers that are currently executing. */ io_outb(ClearReg[DMA_channel], 0x00); /* Send the specified mode to the DMA. */ io_outb(ModeReg[DMA_channel], mode); /* Send the offset address. The first byte is the low base offset, the */ /* second byte is the high offset. */ io_outb(AddrPort[DMA_channel], LOW_BYTE(offset)); io_outb(AddrPort[DMA_channel], HI_BYTE(offset)); /* Send the physical page that the data lies on. */ io_outb(PagePort[DMA_channel], page); /* Send the length of the data. Again, low byte first. */ io_outb(CountPort[DMA_channel], LOW_BYTE(length)); io_outb(CountPort[DMA_channel], HI_BYTE(length)); /* Ok, we're done. Enable the DMA channel (clear the mask). */ io_outb(MaskReg[DMA_channel], DMA_channel); /* Re-enable interrupts before we leave. */ asm_enable_interrupt(); }
/** * Inizializza l'rtc */ void clock_init() { char prev; io_outb(0x70, 0x0B); prev = io_inb(0x71); io_outb(0x70, 0x0B); io_outb(0x71, prev | 0x40); handler_reg(8, &clock_callback); }
/* Normally, IRQs 0 to 7 are mapped to entries 8 to 15. This * is a problem in protected mode, because IDT entry 8 is a * Double Fault! Without remapping, every time IRQ0 fires, * you get a Double Fault Exception, which is NOT actually * what's happening. We send commands to the Programmable * Interrupt Controller (PICs - also called the 8259's) in * order to make IRQ0 to 15 be remapped to IDT entries 32 to * 47 */ void irq_remap(void) { io_outb(0x20, 0x11); io_outb(0xA0, 0x11); io_outb(0x21, 0x20); io_outb(0xA1, 0x28); io_outb(0x21, 0x04); io_outb(0xA1, 0x02); io_outb(0x21, 0x01); io_outb(0xA1, 0x01); io_outb(0x21, 0x0); io_outb(0xA1, 0x0); }
static void ata_cmd_out(int drv_slave, int rwtype, lba_t lba, unsigned count) { CLI_CRIT_BEGIN(1); io_outb(0x1F2, count); io_outb(0x1f3, lba); io_outb(0x1f4, lba >> 8); io_outb(0x1f5, lba >> 16); unsigned char dev = lba >> 24; dev |= drv_slave ? 0xf0 : 0xe0; io_outb(0x1f6, dev); io_outb(0x1f7, rwtype); CLI_CRIT_END(1); }
void default_irq_handler(struct isr_regs *regs) { printk("IRQ handler: #%u, ", regs->int_no); irq_handler handler = handlers[regs->int_no - 32]; if (handler) { printk("calling specific handler\n"); handler(regs); } else printk("no handler specified\n"); if (regs->int_no >= 40) io_outb(IO_PIC2_CMD, OCW2_EOI); io_outb(IO_PIC1_CMD, OCW2_EOI); }
void console_clear(void) { unsigned int i; for(i = 0; i < (80*25); i++) /* Fill the screen with */ { /* background color */ VIDEO_MEMORY[i*2] = 0x20; VIDEO_MEMORY[i*2+1] = 0x07; } io_outb(0x3d4, 0x0f); /* Set the cursor to the */ io_outb(0x3d5, 0); /* upper-left corner of the */ io_outw(0x3d4, 0x0e); /* screen */ io_outb(0x3d5, 0); }/* console_clear */
/* * IRQ handler for the RTC (called twice a second) */ static void rtc_sys_tick(void* ctx) { // Read the RTC register so IRQ will happen again io_outb(0x70, 0x0C); io_inb(0x71); // Only increment time every second if(tick++ == 2) { tick = 0; } else { return; } // Increment seconds if(time.second++ == 59) { time.second = 0; // Increment minutes if(time.minute++ == 59) { time.minute = 0; // Resync with hardware every hour rtc_read(); } } // Reseed PRNG srand(irq_count()); // KDEBUG("%02u:%02u:%02u (%02u-%02u-%04u)", time.hour, time.minute, time.second, time.day, time.month, time.year); }
static void setdata(unsigned char value) { while ((io_inb(REGISTERCONTROL) & STATUSIFULL)); io_outb(REGISTERDATA, value); }
static void setcommand(unsigned char value) { while ((io_inb(REGISTERCONTROL) & STATUSIFULL)); io_outb(REGISTERCONTROL, value); }
/* This gets called from our ASM interrupt handler stub. */ void isr_handler(registers_t regs) { /* This line is important. When the processor extends the 8-bit interrupt number * to a 32bit value, it sign-extends, not zero extends. So if the most significant * bit (0x80) is set, regs.int_no will be very large (about 0xffffff80). */ uint8_t int_no = regs.int_no & 0xFF; /* The IRQ Controllers need to be told when you are done * servicing them, so you need to send them an "End of * Interrupt" command (0x20). There are two 8259 chips: * The first exists at 0x20, the second exists at 0xA0. * If the second controller (an IRQ from 8 to 15) gets * an interrupt, you need to acknowledge the interrupt * at BOTH controllers, otherwise, you only send an EOI * command to the first controller. If you don't send * an EOI, you won't raise any more IRQs */ /* Send an EOI (end of interrupt) signal to the PICs. * If the IDT entry that was invoked was greater than 40 * (meaning IRQ8 - 15), then we need to send an EOI to * the slave controller */ if (int_no >= 40) { /* Send reset signal to slave. */ io_outb(0xA0, 0x20); } /* Send reset signal to master. (As well as slave, if necessary). */ io_outb(0x20, 0x20); if (irq_handlers[int_no] != 0) { isr_t handler = irq_handlers[int_no]; handler(®s); } else { /* Is this a fault whose number is from 0 to 31? */ if (int_no < 32) { /* Display the description for the Exception that occurred. * In this tutorial, we will simply halt the system using an * infinite loop */ log_write("# Warning! Ignoring interrupt: %s Exception\n", exception_messages[int_no]); } else { log_write("# Warning! Unhandled interrupt: 0x%x\n", int_no); } } }
void pit_wait(unsigned int ms) { unsigned short x = 1193 * ms; io_outb(io + REGISTERCOMMAND, COMMANDCHANNEL0 | COMMANDBOTH | COMMANDMODE0); io_outb(io + REGISTERCHANNEL0, x >> 8); io_outb(io + REGISTERCHANNEL0, x); io_outb(io + REGISTERCOMMAND, 0xE2); while (!(io_inb(io + REGISTERCHANNEL0) & (1 << 7))); /* Return old values */ io_outb(io + REGISTERCOMMAND, COMMANDCHANNEL0 | COMMANDBOTH | COMMANDMODE3); io_outb(io + REGISTERCHANNEL0, divisor); io_outb(io + REGISTERCHANNEL0, divisor >> 8); }
static int pit_probe(struct device *devp) { u32 freq; int res; if ((res = irq_handler_reg(IRQ_PIT, &int_handler)) < 0) return res; ticks = 0; freq = PIT_FREQ / 1000; io_outb(PIT_CMD, PIT_RATE); io_outb(PIT_CH0_IO, freq & 0xFF); io_outb(PIT_CH0_IO, (freq >> 8) & 0xFF); devp->op = &pit_file_ops; return 0; }
void do_keyboard() { u8 scan_code = io_inb(0x60); /* 读取扫描码 */ if (!is_queue_full(&kb_queue)) /* 若队列未满则入队,否则放弃该扫描码 */ { en_queue(&kb_queue, scan_code); } io_outb(0x20, 0x20); }
// Called by keyboard driver when Ctrl+Alt+Del is pressed void hid_keyboard_sas(void) { KWARNING("Ctrl+Alt+Del triggered"); uint8_t good = 0x02; while (good & 0x02) { good = io_inb(0x64); } io_outb(0x64, 0xFE); }