gatea20.c revision 1.12 1 1.12 jmcneill /* $NetBSD: gatea20.c,v 1.12 2009/08/23 12:31:05 jmcneill Exp $ */
2 1.1 perry
3 1.1 perry /* extracted from freebsd:sys/i386/boot/biosboot/io.c */
4 1.1 perry
5 1.1 perry #include <sys/types.h>
6 1.1 perry
7 1.1 perry #include <lib/libsa/stand.h>
8 1.1 perry
9 1.1 perry #include "libi386.h"
10 1.4 jdolecek #include "biosmca.h"
11 1.9 ad #include "cpufunc.h"
12 1.1 perry
13 1.1 perry #define K_RDWR 0x60 /* keyboard data & cmds (read/write) */
14 1.1 perry #define K_STATUS 0x64 /* keyboard status */
15 1.1 perry #define K_CMD 0x64 /* keybd ctlr command (write-only) */
16 1.1 perry
17 1.1 perry #define K_OBUF_FUL 0x01 /* output buffer full */
18 1.1 perry #define K_IBUF_FUL 0x02 /* input buffer full */
19 1.1 perry
20 1.1 perry #define KC_CMD_WIN 0xd0 /* read output port */
21 1.1 perry #define KC_CMD_WOUT 0xd1 /* write output port */
22 1.1 perry #define KB_A20 0x9f /* enable A20,
23 1.2 fvdl reset (!),
24 1.1 perry enable output buffer full interrupt
25 1.1 perry enable data line
26 1.1 perry disable clock line */
27 1.1 perry
28 1.1 perry /*
29 1.1 perry * Gate A20 for high memory
30 1.1 perry */
31 1.1 perry static unsigned char x_20 = KB_A20;
32 1.7 junyoung
33 1.7 junyoung void
34 1.7 junyoung gateA20(void)
35 1.1 perry {
36 1.11 ad int biosA20(void);
37 1.9 ad u_long psl;
38 1.9 ad
39 1.11 ad /*
40 1.11 ad * First, try asking the BIOS to enable A20.
41 1.11 ad *
42 1.11 ad * If that fails, try system configuration port 0x92 but only
43 1.11 ad * if known to be necessary. Not all systems enable A20 via the
44 1.11 ad * keyboard controller, some don't have keyboard controllers,
45 1.11 ad * and playing with port 0x92 may cause some systems to break.
46 1.11 ad *
47 1.11 ad * Otherwise, use the traditional method (keyboard controller).
48 1.11 ad */
49 1.11 ad if (!biosA20())
50 1.11 ad return;
51 1.9 ad psl = x86_read_psl();
52 1.9 ad x86_disable_intr();
53 1.5 thorpej if (
54 1.5 thorpej #ifdef SUPPORT_PS2
55 1.5 thorpej biosmca_ps2model == 0xf82 ||
56 1.5 thorpej #endif
57 1.6 manu (inb(K_STATUS) == 0xff && inb(K_RDWR) == 0xff)) {
58 1.6 manu int data;
59 1.6 manu
60 1.6 manu data = inb(0x92);
61 1.6 manu outb(0x92, data | 0x2);
62 1.5 thorpej } else {
63 1.5 thorpej while (inb(K_STATUS) & K_IBUF_FUL);
64 1.6 manu
65 1.5 thorpej while (inb(K_STATUS) & K_OBUF_FUL)
66 1.5 thorpej (void)inb(K_RDWR);
67 1.5 thorpej
68 1.5 thorpej outb(K_CMD, KC_CMD_WOUT);
69 1.6 manu
70 1.5 thorpej while (inb(K_STATUS) & K_IBUF_FUL);
71 1.6 manu
72 1.5 thorpej outb(K_RDWR, x_20);
73 1.6 manu
74 1.5 thorpej while (inb(K_STATUS) & K_IBUF_FUL);
75 1.6 manu
76 1.6 manu while (inb(K_STATUS) & K_OBUF_FUL)
77 1.6 manu (void)inb(K_RDWR);
78 1.4 jdolecek }
79 1.9 ad x86_write_psl(psl);
80 1.1 perry }
81