⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 a20.c

📁 linux 内核源代码
💻 C
字号:
/* -*- linux-c -*- ------------------------------------------------------- * * *   Copyright (C) 1991, 1992 Linus Torvalds *   Copyright 2007 rPath, Inc. - All Rights Reserved * *   This file is part of the Linux kernel, and is made available under *   the terms of the GNU General Public License version 2. * * ----------------------------------------------------------------------- *//* * arch/i386/boot/a20.c * * Enable A20 gate (return -1 on failure) */#include "boot.h"#define MAX_8042_LOOPS	100000static int empty_8042(void){	u8 status;	int loops = MAX_8042_LOOPS;	while (loops--) {		io_delay();		status = inb(0x64);		if (status & 1) {			/* Read and discard input data */			io_delay();			(void)inb(0x60);		} else if (!(status & 2)) {			/* Buffers empty, finished! */			return 0;		}	}	return -1;}/* Returns nonzero if the A20 line is enabled.  The memory address   used as a test is the int $0x80 vector, which should be safe. */#define A20_TEST_ADDR	(4*0x80)#define A20_TEST_SHORT  32#define A20_TEST_LONG	2097152	/* 2^21 */static int a20_test(int loops){	int ok = 0;	int saved, ctr;	set_fs(0x0000);	set_gs(0xffff);	saved = ctr = rdfs32(A20_TEST_ADDR);	while (loops--) {		wrfs32(++ctr, A20_TEST_ADDR);		io_delay();	/* Serialize and make delay constant */		ok = rdgs32(A20_TEST_ADDR+0x10) ^ ctr;		if (ok)			break;	}	wrfs32(saved, A20_TEST_ADDR);	return ok;}/* Quick test to see if A20 is already enabled */static int a20_test_short(void){	return a20_test(A20_TEST_SHORT);}/* Longer test that actually waits for A20 to come on line; this   is useful when dealing with the KBC or other slow external circuitry. */static int a20_test_long(void){	return a20_test(A20_TEST_LONG);}static void enable_a20_bios(void){	asm volatile("pushfl; int $0x15; popfl"		     : : "a" ((u16)0x2401));}static void enable_a20_kbc(void){	empty_8042();	outb(0xd1, 0x64);	/* Command write */	empty_8042();	outb(0xdf, 0x60);	/* A20 on */	empty_8042();}static void enable_a20_fast(void){	u8 port_a;	port_a = inb(0x92);	/* Configuration port A */	port_a |=  0x02;	/* Enable A20 */	port_a &= ~0x01;	/* Do not reset machine */	outb(port_a, 0x92);}/* * Actual routine to enable A20; return 0 on ok, -1 on failure */#define A20_ENABLE_LOOPS 255	/* Number of times to try */int enable_a20(void){	int loops = A20_ENABLE_LOOPS;#if defined(CONFIG_X86_ELAN)	/* Elan croaks if we try to touch the KBC */	enable_a20_fast();	while (!a20_test_long())		;	return 0;#elif defined(CONFIG_X86_VOYAGER)	/* On Voyager, a20_test() is unsafe? */	enable_a20_kbc();	return 0;#else	while (loops--) {		/* First, check to see if A20 is already enabled		   (legacy free, etc.) */		if (a20_test_short())			return 0;		/* Next, try the BIOS (INT 0x15, AX=0x2401) */		enable_a20_bios();		if (a20_test_short())			return 0;		/* Try enabling A20 through the keyboard controller */		empty_8042();		if (a20_test_short())			return 0; /* BIOS worked, but with delayed reaction */		enable_a20_kbc();		if (a20_test_long())			return 0;		/* Finally, try enabling the "fast A20 gate" */		enable_a20_fast();		if (a20_test_long())			return 0;	}	return -1;#endif}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -