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