📄 io.c
字号:
/* * Mach Operating System * Copyright (c) 1992, 1991 Carnegie Mellon University * All Rights Reserved. * * Permission to use, copy, modify and distribute this software and its * documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. * * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. * * Carnegie Mellon requests users of this software to return to * * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU * School of Computer Science * Carnegie Mellon University * Pittsburgh PA 15213-3890 * * any improvements or extensions that they make and grant Carnegie Mellon * the rights to redistribute these changes. * * from: Mach, Revision 2.2 92/04/04 11:35:57 rpd * $FreeBSD: src/sys/i386/boot/biosboot/io.c,v 1.19.2.2 1999/09/05 08:10:24 peter Exp $ */#include "boot.h"#include <machine/cpufunc.h>#include <sys/reboot.h>#define K_RDWR 0x60 /* keyboard data & cmds (read/write) */#define K_STATUS 0x64 /* keyboard status */#define K_CMD 0x64 /* keybd ctlr command (write-only) */#define K_OBUF_FUL 0x01 /* output buffer full */#define K_IBUF_FUL 0x02 /* input buffer full */#define KC_CMD_WIN 0xd0 /* read output port */#define KC_CMD_WOUT 0xd1 /* write output port */#define KB_A20 0xdf /* enable A20, enable output buffer full interrupt enable data line enable clock line */static int getchar(int in_buf);/* * Gate A20 for high memory */voidgateA20(void){#ifdef IBM_L40 outb(0x92, 0x2);#else IBM_L40 while (inb(K_STATUS) & K_IBUF_FUL); while (inb(K_STATUS) & K_OBUF_FUL) (void)inb(K_RDWR); outb(K_CMD, KC_CMD_WOUT); while (inb(K_STATUS) & K_IBUF_FUL); outb(K_RDWR, KB_A20); while (inb(K_STATUS) & K_IBUF_FUL);#endif IBM_L40}/* printf - only handles %d as decimal, %c as char, %s as string */voidprintf(const char *format, ...){ int *dataptr = (int *)&format; char c; dataptr++; while ((c = *format++)) if (c != '%') putchar(c); else switch (c = *format++) { case 'd': { int num = *dataptr++; char buf[10], *ptr = buf; if (num<0) { num = -num; putchar('-'); } do *ptr++ = '0'+num%10; while (num /= 10); do putchar(*--ptr); while (ptr != buf); break; } case 'x': { unsigned int num = *dataptr++, dig; char buf[8], *ptr = buf; do *ptr++ = (dig=(num&0xf)) > 9? 'a' + dig - 10 : '0' + dig; while (num >>= 4); do putchar(*--ptr); while (ptr != buf); break; } case 'c': putchar((*dataptr++)&0xff); break; case 's': { char *ptr = (char *)*dataptr++; while ((c = *ptr++)) putchar(c); break; } }}voidputchar(int c){ if (c == '\n') putchar('\r'); if (loadflags & RB_DUAL) { putc(c); serial_putc(c); } else if (loadflags & RB_SERIAL) serial_putc(c); else putc(c);}static intgetchar(int in_buf){ int c;loop: if (loadflags & RB_DUAL) { if (ischar()) c = getc(); else if (serial_ischar()) c = serial_getc(); else goto loop; } else if (loadflags & RB_SERIAL) c = serial_getc(); else c = getc(); if (c == '\r') c = '\n'; if (c == '\b') { if (in_buf != 0) { putchar('\b'); putchar(' '); } else { goto loop; } } putchar(c); return(c);}/* * This routine uses an inb to an unused port, the time to execute that * inb is approximately 1.25uS. This value is pretty constant across * all CPU's and all buses, with the exception of some PCI implentations * that do not forward this I/O adress to the ISA bus as they know it * is not a valid ISA bus address, those machines execute this inb in * 60 nS :-(. * * XXX this should be converted to use bios_tick. */voiddelay1ms(void){ int i = 800; while (--i >= 0) (void)inb(0x84);}static __inline intisch(void){ int isc; /* * Checking the keyboard has the side effect of enabling clock * interrupts so that bios_tick works. Check the keyboard to * get this side effect even if we only want the serial status. */ isc = ischar(); if (loadflags & RB_DUAL) { if (isc != 0) return (isc); } else if (!(loadflags & RB_SERIAL)) return (isc); return (serial_ischar());}static __inline unsignedpword(unsigned physaddr){ unsigned result; /* * Give the fs prefix separately because gas omits it for * "movl %fs:0x46c, %eax". */ __asm __volatile("fs; movl %1, %0" : "=r" (result) : "m" (*(unsigned *)physaddr)); return (result);}intgets(char *buf){#define bios_tick pword(0x46c)#define BIOS_TICK_MS 55 unsigned initial_bios_tick; char *ptr=buf;#if BOOTWAIT for (initial_bios_tick = bios_tick; bios_tick - initial_bios_tick < BOOTWAIT / BIOS_TICK_MS;)#endif if (isch()) for (;;) { switch(*ptr = getchar(ptr - buf) & 0xff) { case '\n': case '\r': *ptr = '\0'; return 1; case '\b': if (ptr > buf) ptr--; continue; default: ptr++; }#if TIMEOUT + 0#if !BOOTWAIT#error "TIMEOUT without BOOTWAIT"#endif for (initial_bios_tick = bios_tick;;) { if (isch()) break; if (bios_tick - initial_bios_tick >= TIMEOUT / BIOS_TICK_MS) return 0; }#endif } return 0;}intstrcmp(const char *s1, const char *s2){ while (*s1 == *s2) { if (!*s1++) return 0; s2++; } return 1;}voidbcopy(const char *from, char *to, int len){ while (len-- > 0) *to++ = *from++;}/* To quote Ken: "You are not expected to understand this." :) */voidtwiddle(void){ putchar((char)tw_chars); tw_chars = (tw_chars >> 8) | ((tw_chars & (unsigned long)0xFF) << 24); putchar('\b');}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -