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