Home | History | Annotate | Line # | Download | only in lib
      1 /*	$NetBSD: gatea20.c,v 1.12 2009/08/23 12:31:05 jmcneill Exp $	*/
      2 
      3 /* extracted from freebsd:sys/i386/boot/biosboot/io.c */
      4 
      5 #include <sys/types.h>
      6 
      7 #include <lib/libsa/stand.h>
      8 
      9 #include "libi386.h"
     10 #include "biosmca.h"
     11 #include "cpufunc.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 	int biosA20(void);
     37 	u_long psl;
     38 
     39 	/*
     40 	 * First, try asking the BIOS to enable A20.
     41 	 *
     42 	 * If that fails, try system configuration port 0x92 but only
     43 	 * if known to be necessary.  Not all systems enable A20 via the
     44 	 * keyboard controller, some don't have keyboard controllers,
     45 	 * and playing with port 0x92 may cause some systems to break.
     46 	 *
     47 	 * Otherwise, use the traditional method (keyboard controller).
     48 	 */
     49 	if (!biosA20())
     50 		return;
     51 	psl = x86_read_psl();
     52 	x86_disable_intr();
     53 	if (
     54 #ifdef SUPPORT_PS2
     55 	    biosmca_ps2model == 0xf82 ||
     56 #endif
     57 	    (inb(K_STATUS) == 0xff && inb(K_RDWR) == 0xff)) {
     58 		int data;
     59 
     60 		data = inb(0x92);
     61 		outb(0x92, data | 0x2);
     62 	} else {
     63 		while (inb(K_STATUS) & K_IBUF_FUL);
     64 
     65 		while (inb(K_STATUS) & K_OBUF_FUL)
     66 			(void)inb(K_RDWR);
     67 
     68 		outb(K_CMD, KC_CMD_WOUT);
     69 
     70 		while (inb(K_STATUS) & K_IBUF_FUL);
     71 
     72 		outb(K_RDWR, x_20);
     73 
     74 		while (inb(K_STATUS) & K_IBUF_FUL);
     75 
     76 		while (inb(K_STATUS) & K_OBUF_FUL)
     77 			(void)inb(K_RDWR);
     78 	}
     79 	x86_write_psl(psl);
     80 }
     81