
The following is edited from several messages from Kees Bot dated May 4
and 5, 1998. 

From: Kees J Bot <kjb=731391@CS.VU.NL>
Subject: Re: 286 protected mode patch

Below is a patch to klib88.s for the changes I made after I got hold of
HIMEM.ASM, a somewhat old source of HIMEM.SYS.  The A20 en/disable code
is a bit better for the AT, and I also added code to en/disable the A20
line for a PC with an MCA bus, i.e.  most PS/2's.

So if any of you is running 16-bit Minix on a machine with an MCA bus
then this may be for you to get rid of processor=86.  

The PS/2 side of the patch is the great unknown, since I don't have a
PS/2 to test it on.  Who knows, maybe someone will tell us if it works
this time.

Apply the patch like this:
	cd /usr/src/kernel
	patch klib88.s klib88.dif
	cd ../tools
	make hdboot
	shutdown -x 'unset processor;boot'

[Please note that this is experimental, there is another patch in this
directory that attempts to solve the same problems.  Neither may be
correct for every machine. -- asw 12.06.98]
_._. .._ _   ._ ._.. ___ _. __.   _ .... .   _.. ___ _ _ . _..   ._.. .. _. .
*** /save/std/2.0.0/src/kernel/klib88.s	Wed Jul 10 20:17:12 1996
--- klib88.s	Mon May 04 12:20:59 1998
***************
*** 72,75 ****
--- 72,76 ----
  .extern	_vid_mask
  .extern	_level0_func
+ .extern	_ps_mca
  
  	.text
***************
*** 201,205 ****
  	ltr	ax			! set TSS register
  
! 	movb	ah, #0xDF
  	jmp	gate_A20		! enable the A20 address line
  
--- 202,206 ----
  	ltr	ax			! set TSS register
  
! 	movb	ah, #0x02
  	jmp	gate_A20		! enable the A20 address line
  
***************
*** 214,224 ****
  	jae	p2r386
  p2r286:
! 	mov	_gdt+ES_286_OFFSET+DESC_BASE, #0x0400
  	movb	_gdt+ES_286_OFFSET+DESC_BASE_MIDDLE, #0x00
  	mov	ax, #ES_286_SELECTOR
  	mov	es, ax			! BIOS data segment
!   eseg	mov	0x0067, #real		! set return from shutdown address
    cseg	mov	ax, kernel_cs
!   eseg	mov	0x0069, ax
  	movb	al, #0x8F
  	outb	0x70			! select CMOS byte 0x0F (disable NMI)
--- 215,225 ----
  	jae	p2r386
  p2r286:
! 	mov	_gdt+ES_286_OFFSET+DESC_BASE, #0x0000
  	movb	_gdt+ES_286_OFFSET+DESC_BASE_MIDDLE, #0x00
  	mov	ax, #ES_286_SELECTOR
  	mov	es, ax			! BIOS data segment
!   eseg	mov	0x0467, #real		! set return from shutdown address
    cseg	mov	ax, kernel_cs
!   eseg	mov	0x0469, ax
  	movb	al, #0x8F
  	outb	0x70			! select CMOS byte 0x0F (disable NMI)
***************
*** 254,273 ****
  	mov	sp, save_sp		! restore stack
  
! 	movb	ah, #0xDD
  	!jmp	gate_A20		! disable the A20 address line
  
! ! Enable (ah = 0xDF) or disable (ah = 0xDD) the A20 address line.
  gate_A20:
  	call	kb_wait
  	movb	al, #0xD1	! Tell keyboard that a command is coming
  	outb	0x64
  	call	kb_wait
! 	movb	al, ah		! Enable or disable code
  	outb	0x60
  	call	kb_wait
! 	mov	ax, #25		! 25 microsec delay for slow keyboard chip
! 0:	out	0xED		! Write to an unused port (1us)
! 	dec	ax
! 	jne	0b
  	ret
  kb_wait:
--- 255,276 ----
  	mov	sp, save_sp		! restore stack
  
! 	xorb	ah, ah
  	!jmp	gate_A20		! disable the A20 address line
  
! ! Enable (ah = 0x02) or disable (ah = 0x00) the A20 address line.
  gate_A20:
+ 	cmp	_ps_mca, #0	! PS/2 bus?
+ 	jnz	gate_PS_A20
  	call	kb_wait
  	movb	al, #0xD1	! Tell keyboard that a command is coming
  	outb	0x64
  	call	kb_wait
! 	movb	al, #0xDD	! 0xDD = A20 disable code if ah = 0x00
! 	orb	al, ah		! 0xDF = A20 enable code if ah = 0x02
  	outb	0x60
  	call	kb_wait
! 	movb	al, #0xFF	! Pulse output port
! 	outb	0x64
! 	call	kb_wait		! Wait for the A20 line to settle down
  	ret
  kb_wait:
***************
*** 275,278 ****
--- 278,293 ----
  	testb	al, #0x02	! Keyboard input buffer full?
  	jnz	kb_wait		! If so, wait
+ 	ret
+ 
+ gate_PS_A20:		! The PS/2 can twiddle A20 using port A
+ 	inb	0x92		! Read port A
+ 	andb	al, #0xFD
+ 	orb	al, ah		! Set A20 bit to the required state
+ 	outb	0x92		! Write port A
+ 	jmp	.+2		! Small delay
+ A20ok:	inb	0x92		! Check port A
+ 	andb	al, #0x02
+ 	cmpb	al, ah		! A20 line settled down to the new state?
+ 	jne	A20ok		! If not then wait
  	ret
  

