;*********************************************************
;*
;*	386 Protect Memory (High-Memory) Copy program
;*
;*	1991.02.14	make Ken
;*
;*********************************************************
		.386p

rmcode		segment dword public use16 'CODE'
rmcode		ends
pmcode		segment dword public use32 'CODE'
pmcode		ends
incode		segment dword public use16 'CODE'
incode		ends
DGROUP		group	rmcode,pmcode,incode

SEL_NUL		equ	0000h
SEL_PCODE	equ	0008h
SEL_PDATA	equ	0010h
SEL_RCODE	equ	0018h
SEL_RDATA	equ	0020h
SEL_ALL		equ	0028h

rmcode		segment

int_data	dw	?
int_ctl		db	?

ss_seg		dw	?

cpy_src		dd	?
cpy_dis		dd	?
cpy_cnt		dd	?

rm_idtr 	label	pword		; current protected mode IDTR value
rm_idtl 	dw	?		; limit
rm_idtb 	dd	?		; linear base address
rm_gdtr 	label	pword		; current protected mode GDTR value
rm_gdtl 	dw	?		; limit
rm_gdtb 	dd	?		; linear base address

pm_idtr 	label	pword		; current protected mode IDTR value
pm_idtl 	dw	0		; limit
pm_idtb 	dd	0		; linear base address
pm_gdtr 	label	pword		; current protected mode GDTR value
pm_gdtl 	dw	8*6-1		; limit
pm_gdtb 	dd	?		; linear base address

gdt_tbl		label	near
gdt_tbl_null	dd	00000000h,00000000h	; null
gdt_tbl_pcode	dd	0000FFFFh,00409A00h	; base=?,limit=64K,r/e use32
gdt_tbl_pdata	dd	0000FFFFh,00409200h	; base=?,limit=64K,r/w use32
gdt_tbl_rcode	dd	0000FFFFh,00009A00h	; base=?,limit=64K,r/e use16
gdt_tbl_rdata	dd	0000FFFFh,00009200h	; base=?,limit=64K,r/w use16
gdt_tbl_all	dd	0000FFFFh,00CF9200h	; base=0,limit= 4G,r/w use32

		assume	cs:rmcode,ds:DGROUP

nmi_disable	proc	near
		push	ax
		in	al,0002h
		mov	ah,al
		in	al,0012h
		mov	int_data,ax
		mov	al,0FFh
		out	0002h,al
		out	0012h,al
		in	al,060h
		mov	int_ctl,al
		pop	ax
		ret
nmi_disable	endp

nmi_enable	proc	near
		push	ax
		mov	al,int_ctl
		shr	al,2
		and	al,07h
		out	060h,al
		mov	ax,int_data
		out	0012h,al
		mov	al,ah
		out	0002h,al
		pop	ax
		ret
nmi_enable	endp

		public	gdt_init
gdt_init	proc	near
		xor	edx,edx
		mov	dx,cs
		shl	edx,4

		mov	eax,edx
		add	eax,offset gdt_tbl
		mov	pm_gdtb,eax

		mov	eax,edx
		mov	word ptr gdt_tbl_pcode+2,ax
		mov	word ptr gdt_tbl_pdata+2,ax
		mov	word ptr gdt_tbl_rcode+2,ax
		mov	word ptr gdt_tbl_rdata+2,ax
		shr	eax,16
		mov	byte ptr gdt_tbl_pcode+4,al
		mov	byte ptr gdt_tbl_pdata+4,al
		mov	byte ptr gdt_tbl_rcode+4,al
		mov	byte ptr gdt_tbl_rdata+4,al
		mov	byte ptr gdt_tbl_pcode+7,ah
		mov	byte ptr gdt_tbl_pdata+7,ah
		mov	byte ptr gdt_tbl_rcode+7,ah
		mov	byte ptr gdt_tbl_rdata+7,ah

		ret
gdt_init	endp

to_prot		proc	near
		mov	cs_seg,cs
		mov	ss_seg,ss
		cli
		call	nmi_disable
		sgdte	rm_gdtr
		sidte	rm_idtr
		lgdte	pm_gdtr
		lidte	pm_idtr
		mov	eax,cr0
		or	eax,1
		mov	cr0,eax
		jmp	ip_flush
ip_flush:	
		db	0EAh			; far jmp
		dw	offset DGROUP:prot_go
		dw	SEL_PCODE
to_prot		endp

ret_real	proc	near
		mov	eax,cr0
		and	eax,0FFFFFFFEh
		mov	cr0,eax
		db	0EAh
		dw	real_mode
cs_seg		dw	?

real_mode	label	near
		mov	ax,cs
		mov	ds,ax
		mov	ss,ss_seg
		lgdte	rm_gdtr
		lidte	rm_idtr
		call	nmi_enable
		sti
		ret
ret_real	endp

;
; in esi source addr
; in edi copy addr
; in ecx copy byte count
;
		public	hmemcpy
hmemcpy		proc	near
		push	bx
		push	ds
		push	es

		mov	cpy_src,esi
		mov	cpy_dis,edi
		mov	cpy_cnt,ecx
		call	to_prot

		pop	es
		pop	ds
		pop	bx
		ret
hmemcpy		endp

rmcode		ends

pmcode		segment
		assume	cs:pmcode,fs:DGROUP

prot_go		proc	near
		mov	ax,SEL_ALL
		mov	ds,ax
		mov	es,ax
		mov	ax,SEL_PDATA
		mov	fs,ax
		mov	gs,ax

		cld
		mov	esi,fs:cpy_src
		mov	edi,fs:cpy_dis
		mov	ecx,fs:cpy_cnt
		shr	ecx,2
		jecxz	cpy_next
		rep	movsd
cpy_next:
		mov	ecx,fs:cpy_cnt
		and	ecx,3
		jecxz	non_cpy
		rep	movsb
non_cpy:
		mov	ax,SEL_RDATA
		mov	ds,ax
		mov	es,ax
		mov	fs,ax
		mov	gs,ax
		mov	ss,ax

		db	0EAh			; far jmp
		dd	offset DGROUP:ret_real
		dw	SEL_RCODE

prot_go		endp

pmcode		ends

incode		segment
		assume	cs:incode,ds:DGROUP

		public	end_of_adr
end_of_adr	label	byte

msg_str		db	0Dh,0Ah
		db	'IC Memory Card Device Driver ver1.00 for FM-TOWNS'
		db	0Dh,0Ah
		db	'Copyright 1991.03 Nanno-NET(Ken)'
		db	0Dh,0Ah,'$'

		public	open_msg
open_msg	proc	near

		mov	dx,offset DGROUP:msg_str
		mov	ah,9
		int	21h
		ret

open_msg	endp

incode		ends

		end
