;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;                                                              ;;
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License    ;;
;;                                                              ;;
;; Includes source code by Kulakov Vladimir Gennadievich.       ;;
;; Modified by Mario79 and Rus.                                 ;;
;; 02.12.2009 <Lrz>						;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;driver sceletone

format MS COFF

DEBUG        equ 0

include 'proc32.inc'
include 'imports.inc'

API_VERSION	equ 5  ;debug

struc IOCTL
{  .handle	dd ?
   .io_code	dd ?
   .input	dd ?
   .inp_size	dd ?
   .output	dd ?
   .out_size	dd ?
}

virtual at 0
  IOCTL IOCTL
end virtual

public START
public version


DRV_ENTRY    equ 1
DRV_EXIT     equ -1
STRIDE	     equ 4	;size of row in devices table

SRV_GETVERSION	equ 0

section '.flat' code readable align 16

proc START stdcall, state:dword

	   cmp [state], 1
	   jne .exit
.entry:
	;Detect_COM_Mouse:
if DEBUG
	mov    esi, msgInit
	call   Boot_Log
end if
	mov    bx, 0x3f8
	call   MSMouseSearch
	cmp    AL,'M'
	jne    @f
	;mov    [com1_mouse_detected],1
	;mov     [irq_owner+4*4], 1      ; IRQ4 owner is System

	mov	dx, bx
	inc	dx			 ; 0x3f8 + 1
	mov	al, 1
	out	dx, al

	stdcall AttachIntHandler, 4, irq4_handler, dword 0
if DEBUG
	test	eax, eax
	jne	.label1

	mov	esi, msg_error_attach_int_handler
	call	Boot_Log
end if
     .label1:
;	mov	eax, 0
;	mov	ebx, 0x3F8
;	mov	ecx, 0x3FF
	xor	ebx,ebx
	mov	ecx, 0x3F8
	mov	edx, 0x3FF
	call	ReservePortArea

if DEBUG
	cmp	eax, 1
	jne	.go

	mov	esi, msg_error_reserve_ports
	call	Boot_Log

     .go:
	mov	esi,boot_setmouse_type
	call	Boot_Log
end if
     @@:
	mov	bx, 0x2f8
	call	MSMouseSearch
	cmp	AL,'M'
	jne	.resume
	;mov     [com2_mouse_detected],1
	;mov     [irq_owner+3*4], 1      ; IRQ3 owner is System

	stdcall AttachIntHandler, 3, irq3_handler, dword 0

;	mov	eax, 0
;	mov	ebx, 0x2F8
;	mov	ecx, 0x3F8
	xor	ebx,ebx
	mov	ecx, 0x2F8
	mov	edx, 0x3F8

	call	ReservePortArea
if DEBUG
	cmp	eax, 1
	jne	@f

	mov	esi, msg_error_reserve_ports
	call	Boot_Log
      @@:

	mov	esi,boot_setmouse_type + 22
	call	Boot_Log
end if
      .resume:

	   stdcall RegService, my_service, service_proc
if DEBUG
	   test	eax, eax
	   jne	@f

	   mov	esi, msg_exit
	   call Boot_Log
end if
	 @@:
	   ret
.fail:
.exit:
if DEBUG
	   mov	esi, msg_exit
	   call Boot_Log
end if
	   xor eax, eax
	   ret
endp

handle	   equ	IOCTL.handle
io_code    equ	IOCTL.io_code
input	   equ	IOCTL.input
inp_size   equ	IOCTL.inp_size
output	   equ	IOCTL.output
out_size   equ	IOCTL.out_size

align 4
proc service_proc stdcall, ioctl:dword

	   mov ebx, [ioctl]
	   mov eax, [ebx+io_code]
	   cmp eax, SRV_GETVERSION
	   jne @F

	   mov eax, [ebx+output]
	   cmp [ebx+out_size], 4
	   jne .fail
	   mov [eax], dword API_VERSION
	   xor eax, eax
	   ret
@@:
.fail:
	   or eax, -1
	   ret
endp

align 4
MSMouseSearch:
	; ����� ���� ����� COM-�����
MouseSearch:
	; ������������� ��������
	; ������/�������� 1200 ���
	; in bx COM Port Base Address
	mov	DX, bx
	add	DX,3
	in	AL,DX
	or	AL,80h	;���������� ��� DLAB
	out	DX,AL
	mov	DX, bx
	mov	AL,60h	;1200 ���
	out	DX,AL
	inc	DX
	mov	AL,0
	out	DX,AL
	; ���������� ����� ����� 7 ���, 1 �������� ���,
	; �������� �� ��������������
	mov	DX, bx
	add	DX,3
	mov	AL,00000010b
	out	DX,AL
	; ��������� ��� ���������
	mov	dx, bx
	inc	dx
	mov	AL,0
	out	DX,AL
; ���������, ��� ���������� ���������� � �������
; ����� ���� MSMouse
	; ��������� ������� ���� � ���������
	mov	DX, bx
	add	EDX,4	;������� ���������� �������
	mov	AL,0	;�������� DTR, RTS � OUT2
	out	DX,AL
	; ������� 5 "�����" (0,2 �)
	mov	ecx, 0xFFFF
	loop	$
	; �������� ������� ����
	mov	al, 1
	out	dx, al
	mov	ecx, 0xFFFF
	loop	$
	; �������� ������� ������
	mov	dx, bx
	in	AL,DX
	add	edx, 4
	mov	AL, 1011b  ;���������� DTR � RTS � OUT2
	out	DX,AL
	mov	ecx, 0x1FFFF
; ���� ������ �����
WaitData:
	; ������� ��� 10 "�����"
	 dec  ecx
;	 cmp  ecx,0
	 jz	NoMouse
	; ��������� ������� ������������������ �����
	mov	DX, bx
	add	DX,5
	in	AL,DX
	test	AL,1   ;������ ������?
	jz	WaitData
	; ������ ������
	mov	DX, bx
	in	AL,DX
NoMouse:
	ret

align 4
irq3_handler:
	mov	dx, 0x2f8
	mov	esi, com2_mouse
	jmp	irq_handler

align 4
irq4_handler:
	mov	dx, 0x3f8
	mov	esi, com1_mouse

irq_handler:

; in: esi -> COM_MOUSE_DATA struc, dx = base port (xF8h)
	add	edx, 5		; xFDh
	in	al, dx
	test	al, 1		; ������ ������?
	jz	.Error
; ������ ������
	sub	edx, 5
	in	al, dx
; �������� ������� ���������� ���
	and	al, 01111111b

; ���������� ���������� ����� ������������ �����
	cmp	[esi+COM_MOUSE_DATA.MouseByteNumber], 2
	ja	.Error
	jz	.ThirdByte
	jp	.SecondByte
; ��������� ������ ���� ������
.FirstByte:
	test	al, 1000000b	; ������ ���� �������?
	jz	.Error
	mov	[esi+COM_MOUSE_DATA.FirstByte], al
	inc	[esi+COM_MOUSE_DATA.MouseByteNumber]
	jmp	.EndMouseInterrupt
; ��������� ������ ���� ������
.SecondByte:
	test	al, 1000000b
	jnz	.Error
	mov	[esi+COM_MOUSE_DATA.SecondByte], al
	inc	[esi+COM_MOUSE_DATA.MouseByteNumber]
	jmp	.EndMouseInterrupt
; ��������� ������ ���� ������
.ThirdByte:
	test	al, 1000000b
	jnz	.Error
	mov	[esi+COM_MOUSE_DATA.ThirdByte], al
	mov	[esi+COM_MOUSE_DATA.MouseByteNumber], 0
; (����� ������ �� ���� ������ ���������).
; �������� ����� �������� ��������� ������ ����
	mov	al, [esi+COM_MOUSE_DATA.FirstByte]
	mov	ah, al
	shr	al, 3
	and	al, 2
	shr	ah, 5
	and	ah, 1
	add	al, ah
	movzx	eax, al
	mov	[BTN_DOWN], eax

; ��������� ����������� �� X � ���������� X
	mov	al, [esi+COM_MOUSE_DATA.FirstByte]
	shl	al, 6
	or	al, [esi+COM_MOUSE_DATA.SecondByte]

	cbw
	movzx	eax, ax
	mov	[MOUSE_X], eax

; ��������� ����������� �� Y � ���������� Y
	mov	al, [esi+COM_MOUSE_DATA.FirstByte]
	and	al, 00001100b
	shl	al, 4
	or	al, [esi+COM_MOUSE_DATA.ThirdByte]

	cbw
	movzx	eax, ax
	neg	eax
	mov	[MOUSE_Y], eax

	stdcall SetMouseData, [BTN_DOWN], [MOUSE_X], [MOUSE_Y], 0, 0

	jmp	.EndMouseInterrupt

.Error:
; ��������� ���� � ������� �������� ���������� ��
; ����, �������� ������� ������ ������ ������

	mov	[esi+COM_MOUSE_DATA.MouseByteNumber],0
.EndMouseInterrupt:

	ret

;all initialized data place here

align 4

struc COM_MOUSE_DATA {
; ����� ������������ �� ���� �����
	.MouseByteNumber	db	?
; ������������ ��������� ������, ������������ �����
	.FirstByte		db	?
	.SecondByte		db	?
	.ThirdByte		db	?
	;.timer_ticks_com        dd      ?
}
virtual at 0
 COM_MOUSE_DATA COM_MOUSE_DATA
end virtual

com1_mouse COM_MOUSE_DATA
com2_mouse COM_MOUSE_DATA

MOUSE_X      dd 0
MOUSE_Y      dd 0
BTN_DOWN     dd 0

COMPortBaseAddr dw 3F8h



version      dd (5 shl 16) or (API_VERSION and 0xFFFF)

my_service   db 'COM_Mouse',0  ;max 16 chars include zero

if DEBUG
msgInit 		     db   'Preved bugoga!',13,10,0
boot_setmouse_type	     db   'Detected - COM1 mouse',13,10,0
			     db   'Detected - COM2 mouse',13,10,0
msg_error_reserve_ports      db   'Error reserving ports!',13,10,0
msg_error_attach_int_handler db   'Error attach interrupt handler!',13,10,0
msg_exit		     db   'Exit!',13,10,0
end if

section '.data' data readable writable align 16

;all uninitialized data place here