wok-next diff syslinux/stuff/iso2exe/a20.c @ rev 16069

syslinux/iso2exe: add a20 support
author Pascal Bellard <pascal.bellard@slitaz.org>
date Thu Mar 13 08:22:47 2014 +0000 (2014-03-13)
parents
children 3e7ad70145ce
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/syslinux/stuff/iso2exe/a20.c	Thu Mar 13 08:22:47 2014 +0000
     1.3 @@ -0,0 +1,142 @@
     1.4 +#ifndef __A20
     1.5 +#define __A20
     1.6 +
     1.7 +// http://www.win.tue.nl/~aeb/linux/kbd/A20.html
     1.8 +static void a20enable(void)
     1.9 +{
    1.10 +#asm
    1.11 +		call	a20test
    1.12 +
    1.13 +		in	al, 0x92	// fast A20
    1.14 +		test	al, #0x2
    1.15 +		jnz	no92
    1.16 +		or	al, #0x2	// Enable A20
    1.17 +		and	al, #0xFE	// Do not reset machine
    1.18 +		out	0x92, al
    1.19 +		call	a20test
    1.20 +no92:
    1.21 +		call	empty_8042
    1.22 +		mov	al, #0xD1	// command write
    1.23 +		out	0x64, al 
    1.24 +		call	empty_8042
    1.25 +		mov	al, #0xDF	// Enable A20
    1.26 +		out	0x60, al 
    1.27 +		call	empty_8042
    1.28 +
    1.29 +		mov	al, #0xFF	// Null command, but UHCI wants it
    1.30 +		out	0x64, al 
    1.31 +		call	empty_8042
    1.32 +		call	a20test
    1.33 +		
    1.34 +		mov	ax, #0x2401
    1.35 +		int	0x15
    1.36 +		call	a20test
    1.37 +		
    1.38 +		in	al, 0xEE	// fast enable A20
    1.39 +		jmp	a20test
    1.40 +
    1.41 +empty_8042:
    1.42 +		mov	ah, #-32
    1.43 +wait_8042:
    1.44 +		in	al, 0x64
    1.45 +		inc	ax		// FF 32x : no kbd
    1.46 +		jz	enabled
    1.47 +		dec	ax
    1.48 +		shr	ax, #1		// Bit 0: input data
    1.49 +		jc	data
    1.50 +		shr	ax, #1		// Bit 1: buffer empty
    1.51 +		jc	wait_8042
    1.52 +		ret
    1.53 +data:
    1.54 +		in	al, 0x60	// read data
    1.55 +		jmp	wait_8042
    1.56 +a20test:
    1.57 +		push	ds
    1.58 +		xor	cx, cx
    1.59 +		xor	bx, bx
    1.60 +		mov	ds, cx		// ds = 0000
    1.61 +		dec	cx
    1.62 +		mov	gs, cx		// gs = FFFF
    1.63 +		cli
    1.64 +a1:
    1.65 +		mov	ax, [bx]
    1.66 +		not	ax
    1.67 +		mov	dx, ax
    1.68 +		seg	gs
    1.69 +		xchg	dx, [bx+10]
    1.70 +		cmp	ax, [bx]
    1.71 +		seg	gs
    1.72 +		mov	[bx+10], dx
    1.73 +		loopne	a1
    1.74 +		pop	ds
    1.75 +		xchg	ax, cx
    1.76 +		sti
    1.77 +		jne	enabled
    1.78 +		pop	cx		// quit a20enable
    1.79 +enabled:
    1.80 +		ret			// ax != 0 : enabled
    1.81 +#endasm
    1.82 +}
    1.83 +
    1.84 +#define A20HOLDBUFFER	0x80000
    1.85 +static int a20buffer = 0;
    1.86 +static void movehia20(void)
    1.87 +{
    1.88 +	if ((mem.base - 0x100000UL) >= 0x10000UL) {
    1.89 +		movehi();
    1.90 +		return;
    1.91 +	}
    1.92 +	a20buffer = 1;
    1.93 +#asm
    1.94 +		pusha
    1.95 +		push	#A20HOLDBUFFER/16
    1.96 +		pop	es
    1.97 +		mov	di, _mem	// mem.base & 0xFFFF
    1.98 +		mov	si, #_buffer
    1.99 +		mov	cx, #BUFFERSZ/2
   1.100 +		cld
   1.101 +		rep
   1.102 +		  movsw
   1.103 +		popa
   1.104 +#endasm
   1.105 +}
   1.106 +#define movehi movehia20
   1.107 +
   1.108 +#define REALMODE_SWITCH _realmode_switch_a20
   1.109 +static void realmode_switch_a20(void)
   1.110 +{
   1.111 +	if (!a20buffer) return;
   1.112 +	a20enable();
   1.113 +#asm
   1.114 +		pusha
   1.115 +		xor	di, di		// 30
   1.116 +		mov	cx, #9		// 2E..1E
   1.117 +a20z1:
   1.118 +		push	di
   1.119 +		loop	a20z1
   1.120 +		push	#0x10
   1.121 +		push	di		// 1A 0x100000
   1.122 +		push	#-1		// 18
   1.123 +		push	di		// 16
   1.124 +		push	#A20HOLDBUFFER/0x10000
   1.125 +		push	di		// 12 A20HOLDBUFFER
   1.126 +		push	#-1		// 10
   1.127 +		mov	cl, #8		// 0E..00
   1.128 +a20z2:
   1.129 +		push	di
   1.130 +		loop	a20z2
   1.131 +		mov	ch, #0x10000/512
   1.132 +		push	ss
   1.133 +		pop	es
   1.134 +		mov	si, sp
   1.135 +		mov	ax, #0x8793
   1.136 +		mov	[si+0x15], al
   1.137 +		xchg	[si+0x1D], al
   1.138 +		xchg	[si+0x1F], al	// bits 24..31
   1.139 +		int	0x15
   1.140 +		add	sp, #0x30
   1.141 +		popa
   1.142 +#endasm
   1.143 +}
   1.144 +
   1.145 +#endif