2 * Mach Operating System
3 * Copyright (c) 1992, 1991 Carnegie Mellon University
6 * Permission to use, copy, modify and distribute this software and its
7 * documentation is hereby granted, provided that both the copyright
8 * notice and this permission notice appear in all copies of the
9 * software, derivative works or modified versions, and any portions
10 * thereof, and that both notices appear in supporting documentation.
12 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
16 * Carnegie Mellon requests users of this software to return to
18 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
19 * School of Computer Science
20 * Carnegie Mellon University
21 * Pittsburgh PA 15213-3890
23 * any improvements or extensions that they make and grant Carnegie Mellon
24 * the rights to redistribute these changes.
26 * from: Mach, Revision 2.2 92/04/04 11:35:57 rpd
27 * $FreeBSD: src/sys/i386/boot/biosboot/io.c,v 1.26 1999/08/28 00:43:13 peter Exp $
28 * $DragonFly: src/sys/platform/pc32/boot/biosboot/Attic/io.c,v 1.2 2003/06/17 04:28:34 dillon Exp $
32 #include <machine/cpufunc.h>
33 #include <sys/reboot.h>
35 #define K_RDWR 0x60 /* keyboard data & cmds (read/write) */
36 #define K_STATUS 0x64 /* keyboard status */
37 #define K_CMD 0x64 /* keybd ctlr command (write-only) */
39 #define K_OBUF_FUL 0x01 /* output buffer full */
40 #define K_IBUF_FUL 0x02 /* input buffer full */
42 #define KC_CMD_WIN 0xd0 /* read output port */
43 #define KC_CMD_WOUT 0xd1 /* write output port */
44 #define KB_A20 0xdf /* enable A20,
45 enable output buffer full interrupt
50 static int getchar(int in_buf);
53 * Gate A20 for high memory
61 while (inb(K_STATUS) & K_IBUF_FUL);
62 while (inb(K_STATUS) & K_OBUF_FUL)
65 outb(K_CMD, KC_CMD_WOUT);
66 while (inb(K_STATUS) & K_IBUF_FUL);
68 while (inb(K_STATUS) & K_IBUF_FUL);
72 /* printf - only handles %d as decimal, %c as char, %s as string */
75 printf(const char *format, ...)
77 int *dataptr = (int *)&format;
81 while ((c = *format++))
85 switch (c = *format++) {
88 char buf[10], *ptr = buf;
102 unsigned int num = *dataptr++, dig;
103 char buf[8], *ptr = buf;
105 *ptr++ = (dig=(num&0xf)) > 9?
114 case 'c': putchar((*dataptr++)&0xff); break;
116 char *ptr = (char *)*dataptr++;
129 if (loadflags & RB_DUAL) {
132 } else if (loadflags & RB_SERIAL)
144 if (loadflags & RB_DUAL) {
147 else if (serial_ischar())
151 } else if (loadflags & RB_SERIAL)
170 * This routine uses an inb to an unused port, the time to execute that
171 * inb is approximately 1.25uS. This value is pretty constant across
172 * all CPU's and all buses, with the exception of some PCI implentations
173 * that do not forward this I/O adress to the ISA bus as they know it
174 * is not a valid ISA bus address, those machines execute this inb in
177 * XXX this should be converted to use bios_tick.
193 * Checking the keyboard has the side effect of enabling clock
194 * interrupts so that bios_tick works. Check the keyboard to
195 * get this side effect even if we only want the serial status.
199 if (loadflags & RB_DUAL) {
202 } else if (!(loadflags & RB_SERIAL))
204 return (serial_ischar());
207 static __inline unsigned
208 pword(unsigned physaddr)
213 * Give the fs prefix separately because gas omits it for
214 * "movl %fs:0x46c, %eax".
216 __asm __volatile("fs; movl %1, %0" : "=r" (result)
217 : "m" (*(unsigned *)physaddr));
224 #define bios_tick pword(0x46c)
225 #define BIOS_TICK_MS 55
226 unsigned initial_bios_tick;
230 for (initial_bios_tick = bios_tick;
231 bios_tick - initial_bios_tick < BOOTWAIT / BIOS_TICK_MS;)
235 switch(*ptr = getchar(ptr - buf) & 0xff) {
241 if (ptr > buf) ptr--;
248 #error "TIMEOUT without BOOTWAIT"
250 for (initial_bios_tick = bios_tick;;) {
253 if (bios_tick - initial_bios_tick >=
254 TIMEOUT / BIOS_TICK_MS)
263 strcmp(const char *s1, const char *s2)
275 strcasecmp(const char *s1, const char *s2)
278 * We only consider ASCII chars and don't anticipate
279 * control characters (they are invalid in filenames
282 while ((*s1 & 0x5f) == (*s2 & 0x5f)) {
292 bcopy(const void *from, void *to, size_t len)
294 char *fp = (char *)from;
295 char *tp = (char *)to;
301 /* To quote Ken: "You are not expected to understand this." :) */
306 putchar((char)tw_chars);
307 tw_chars = (tw_chars >> 8) | ((tw_chars & (unsigned long)0xFF) << 24);