xref: /netbsd-src/sys/arch/i386/stand/lib/gatea20.c (revision aaf4ece63a859a04e37cf3a7229b5fab0157cc06)
1 /*	$NetBSD: gatea20.c,v 1.8 2005/12/11 12:17:48 christos Exp $	*/
2 
3 /* extracted from freebsd:sys/i386/boot/biosboot/io.c */
4 
5 #include <sys/types.h>
6 #include <machine/pio.h>
7 
8 #include <lib/libsa/stand.h>
9 
10 #include "libi386.h"
11 #include "biosmca.h"
12 
13 #define K_RDWR 		0x60		/* keyboard data & cmds (read/write) */
14 #define K_STATUS 	0x64		/* keyboard status */
15 #define K_CMD	 	0x64		/* keybd ctlr command (write-only) */
16 
17 #define K_OBUF_FUL 	0x01		/* output buffer full */
18 #define K_IBUF_FUL 	0x02		/* input buffer full */
19 
20 #define KC_CMD_WIN	0xd0		/* read  output port */
21 #define KC_CMD_WOUT	0xd1		/* write output port */
22 #define KB_A20		0x9f		/* enable A20,
23 					   reset (!),
24 					   enable output buffer full interrupt
25 					   enable data line
26 					   disable clock line */
27 
28 /*
29  * Gate A20 for high memory
30  */
31 static unsigned char	x_20 = KB_A20;
32 
33 void
34 gateA20(void)
35 {
36 	__asm("pushfl ; cli");
37 	/*
38 	 * Not all systems enable A20 via the keyboard controller.
39 	 *	* IBM PS/2 L40
40 	 *	* AMD Elan SC520-based systems
41 	 */
42 	if (
43 #ifdef SUPPORT_PS2
44 	    biosmca_ps2model == 0xf82 ||
45 #endif
46 	    (inb(K_STATUS) == 0xff && inb(K_RDWR) == 0xff)) {
47 		int data;
48 
49 		data = inb(0x92);
50 		outb(0x92, data | 0x2);
51 	} else {
52 		while (inb(K_STATUS) & K_IBUF_FUL);
53 
54 		while (inb(K_STATUS) & K_OBUF_FUL)
55 			(void)inb(K_RDWR);
56 
57 		outb(K_CMD, KC_CMD_WOUT);
58 
59 		delay(100);
60 		while (inb(K_STATUS) & K_IBUF_FUL);
61 
62 		outb(K_RDWR, x_20);
63 
64 		delay(100);
65 		while (inb(K_STATUS) & K_IBUF_FUL);
66 
67 		while (inb(K_STATUS) & K_OBUF_FUL)
68 			(void)inb(K_RDWR);
69 	}
70 	__asm("popfl");
71 }
72