; ****************************************************************************
; TRDOS386.ASM (TRDOS 386 Kernel - v2.0.0) - MAIN PROGRAM : trdosk8.s
; ----------------------------------------------------------------------------
; Last Update: 10/06/2016
; ----------------------------------------------------------------------------
; Beginning: 24/01/2016
; ----------------------------------------------------------------------------
; Assembler: NASM version 2.11 (trdos386.s)
; ----------------------------------------------------------------------------
; Derived from 'Retro UNIX 386 Kernel - v0.2.1.0' source code by Erdogan Tan
; u0.s (20/11/2015), u4.s (14/10/2015)
; ****************************************************************************

set_run_sequence:
	; 10/06/2016
	; 22/05/2016
	; 20/05/2016
	; 19/05/2016 - TRDOS 386 (TRDOS v2.0)
	; TRDOS 386 feature only !
	;
	; INPUT ->
	;	AL = process number (next process)
	;
	;	this process must be added to run sequence
	;
	;	[u.pri] = priority of present process
	;
	;	DL = priority (queue)
	;	     0 = background (low) ; run on background 
	;	     1 = regular (normal) ; run as regular
	;	     2 = event (high)     ; run for event
	;
	;	1) If the requested process is already running:
	;	   a) If present priority is high ([u.pri]=2) 
	;	      and requested priority is also high, 
	;	      there is nothing to do! Because it has been
	;	      done already (before this attempt).		 	
	;	   b) If present priority is high ([u.pri]=2)
	;	      and requested priority is not high, there is
	;	      nothing to do! Because, it's current
	;	      run queue is unspecified, here. (It may be in
	;	      a waiting list or in a run queue; if the new
	;	      priority would be used to add it to relavant
        ;             run queue, this would be wrong, unnecessary
	;	      and destabilizing duplication!)
	;	   c) If present priority is not high ([u.pri]<2)
        ;             and requested priority is high (event),
	;	      process will be added to present priority's
	;	      run queue and then, priority will be changed
	;	      to high ([u.pri]=2).
	;	   d) If present priority is not high ([u.pri]<2)
	;	      and requested priority is not high, [u.pri]
	;	      value will be changed. There is nothing to do
	;	      in addition. (The new priority value will be
	;	      used by 'tswap/tswitch' procedure at 'sysret'
	;	      or 'sysrele' stage.)
	;
	;	2) If the requested process is not running:
	;	   a) If requested priority of the requested
	;	      (next) process is high (event) and priority
	;	      of present process is not high, the requested
	;	      process will be added to ('runq_event') high
	;	      priority run queue and then present (running)
	;	      process will be stopped (swapped/switched out)
	;	      immediately if it is in user mode, or it's 
	;	      [u.quant] value will be reset to 0 and (then) 
	;	      it will be stopped at 'sysret' stage.			
	;	   b) If requested priority of the requested
	;	      (next) process is high (event) and priority
	;	      of present process is also high, the requested
	;	      process will be added to ('runq_event') high
	;	      priority run queue and present (running) 
	;	      process will be allowed to run until it's 
	;	      time quantum will be elapsed ([u.quant]=0).	
	;	   c) If requested priority of the requested
	;	      (next) process is not high ('run for event'), 
	;	      there is nothing to do. Because, it's current
	;	      run queue is unspecified, here. (It may be in
	;	      a waiting list or in a run queue; if the new
	;	      priority would be used to add it to relavant
        ;             run queue, this would be wrong, unnecessary
	;	      and destabilizing duplication!) 
	;
	; OUTPUT ->
	;	none
	;
	;	[u.pri] = priority of present process
	;
	;	cf = 1, if the request could not be fulfilled.
	;			 	     	  
	;	NOTE: 
        ;          * Processes in 'run as regular' queue can run
	;	     if there is no process in 'run for event' queue
	;	     ('run for event' processes have higher priority)	 		 
	;	   * When [u.quant] time quantum of a process is
	;	     elapsed, it's high priority ('run for event')
	;	     status will be disabled, it can be run in sequence
	;	     of it's actual run queue.
	;	   * A 'run on background' process will always be 
	;	     sequenced in 'run on background' (low priority)
	;	     queue, it can run only when other priority queues
	;	     are empty. (idle time processes, e.g. printing)  	 	
	;
	; Modified registers: eax, ebx, edx, edi
	;

srunseq_0:
	mov	ebx, eax
	xor	eax, eax
	mov	edi, p.pid
srunseq_1:
        cmp     al, [u.uno]     ; same process ?
	jne	short srunseq_4 ; no

	mov	ah, [u.pri] 	; present/current priority
	cmp	ah, 2       	; 'run for event' priority level
	jb	short srunseq_8 ; no

srunseq_2:
	; there is nothing to do!
	retn

srunseq_3:
        cmp     al, nproc       ; number of processes = 16 
	jnb	short srunseq_7 ; 'p.pid' values do not match !!!???

	inc	edi
	inc	edi
	jmp	short srunseq_1

srunseq_4:
	; dl = priority
	cmp	dl, 2 		; event queue
	jb	short srunseq_2 ; requested process is not present
				; process and priority of requested
				; process is not high (event), 
				; there is nothing to do!
	
	; requested process is not present process
	; & priority of requested process is high
	cmp	dl, [u.pri] 	; priority of present process
	jna	short srunseq_5 ; is high, also
	;
	; present process will be swapped/switched out
	inc	byte [p_change] ; 1

srunseq_5:
	; add process to 'runq_event' queue for new event
	mov	ebx, runq_event ; high priority run queue

srunseq_6:
	; al = process number
	; ebx = run queue
	call	putlu
	retn

srunseq_7:
	cmc
	retn

srunseq_8:
	; present priority of the process is not high
	
	mov	[u.pri], dl ; new priority 
			    ; (will be used by 'tswap')

	cmp	dl, 2 		; high priority ?
	jb	short srunseq_7 ; no, there is nothing to do
				; in addition

	; process must be added to relevant run queue, here!
	; (new priority is high/event priority and process
	; will not be added to a run queue by 'tswap')

	mov	ebx, runq_normal ; 'run as regular' queue

	and	ah, ah  ;  previous value of [u.pri]
	jnz	short srunseq_6

	inc	ebx
	inc	ebx
	; ebx = runq_background ; 'run on backgroud' queue 

	jmp	short srunseq_6

clock:
	; 23/05/2016
	; 22/05/2016
	; 20/05/2016
	; 19/05/2016 - TRDOS 386 (TRDOS v2.0)
	; 14/05/2015 - 14/10/2015 (Retro UNIX 386 v1)
	; 07/12/2013 - 10/04/2014 (Retro UNIX 8086 v1)

	cmp	byte [u.quant], 0
	ja	short clk_1
	;
	cmp     byte [u.uno], 1 ; /etc/init ? (for Retro UNIX 8086 & 386 v1)
				; MainProg (Kernel's Command Interpreter)
				; for TRDOS 386.
	jna	short clk_1 ; yes, do not swap out
	;
	cmp     byte [sysflg], 0FFh ; user or system space ?
	jne	short clk_2 	    ; system space (sysflg <> 0FFh)
	;
	cmp	word [u.intr], 0
	jna	short clk_2
	;
	; 23/05/2016
	cmp	byte [multi_tasking], 0
	jna	short clk_2
	;
	inc	byte [p_change] ; it is time to change running process	
	retn
clk_1:
	dec	byte [u.quant]
clk_2:
	retn   ; return to (hardware) timer interrupt routine


; 29/04/2016 - TRDOS 386 (TRDOS v2.0)
int34h:  ; #IOCTL# (I/O port access support for ring 3)
	iretd

INT4Ah:
	; 24/01/2016
	; this procedure will be called by 'RTC_INT' (in 'timer.s')
	retn

; u0.s
; Retro UNIX 386 v1 Kernel (v0.2) - SYS0.INC
; Last Modification: 20/11/2015

com2_int:
	; 07/11/2015 
	; 24/10/2015
	; 23/10/2015
	; 14/03/2015 (Retro UNIX 386 v1 - Beginning)
	; 28/07/2014 (Retro UNIX 8086 v1)
	; < serial port 2 interrupt handler >
	;
	mov 	[esp], eax ; overwrite call return address
	;push	eax
	mov	ax, 9
	jmp	short comm_int
com1_int:
	; 07/11/2015
	; 24/10/2015
	mov 	[esp], eax ; overwrite call return address
	; 23/10/2015
	;push	eax
	mov	ax, 8
comm_int:
	; 20/11/2015
	; 18/11/2015
	; 17/11/2015
	; 16/11/2015
	; 09/11/2015
	; 08/11/2015
	; 07/11/2015
	; 06/11/2015 (serial4.asm, 'serial')	
	; 01/11/2015
	; 26/10/2015
	; 23/10/2015
	push	ebx
	push	esi
	push	edi
	push 	ds
	push 	es
	; 18/11/2015
	mov	ebx, cr3
	push	ebx ; ****
	;
	push	ecx ; ***
	push	edx ; **
	;
	mov	ebx, KDATA
	mov	ds, bx
	mov	es, bx
	;
	mov	ecx, [k_page_dir]
	mov	cr3, ecx
	; 20/11/2015
	; Interrupt identification register
	mov	dx, 2FAh ; COM2
	;
	cmp 	al, 8 
	ja 	short com_i0
	;
	; 20/11/2015
	; 17/11/2015
	; 16/11/2015
	; 15/11/2015
	; 24/10/2015
	; 14/03/2015 (Retro UNIX 386 v1 - Beginning)
	; 28/07/2014 (Retro UNIX 8086 v1)
	; < serial port 1 interrupt handler >
	;
	inc	dh ; 3FAh ; COM1 Interrupt id. register
com_i0:
	;push	eax ; *
	; 07/11/2015
	mov 	byte [ccomport], al
	; 09/11/2015
	movzx	ebx, ax ; 8 or 9
	; 17/11/2015
 	; reset request for response status
	mov	[ebx+req_resp-8], ah ; 0
	;
	; 20/11/2015
	in	al, dx		; read interrupt id. register
	JMP	$+2	   	; I/O DELAY
	and	al, 4		; received data available?	
	jz	short com_eoi	; (transmit. holding reg. empty)
	;
	; 20/11/2015
	sub	dl, 3FAh-3F8h	; data register (3F8h, 2F8h)
	in	al, dx     	; read character
	;JMP	$+2	   	; I/O DELAY
	; 08/11/2015
	; 07/11/2015
	mov	esi, ebx 
	mov	edi, ebx
	add 	esi, rchar - 8 ; points to last received char
	add	edi, schar - 8 ; points to last sent char
	mov	[esi], al ; received char (current char)
	; query
	and	al, al
	jnz	short com_i2
   	; response
	; 17/11/2015
	; set request for response status
        inc     byte [ebx+req_resp-8] ; 1 
	;
	add	dx, 3FDh-3F8h	; (3FDh, 2FDh)
	in	al, dx	   	; read line status register 
	JMP	$+2	   	; I/O DELAY
	and	al, 20h	   	; transmitter holding reg. empty?
	jz	short com_eoi 	; no
	mov 	al, 0FFh   	; response			
	sub	dx, 3FDh-3F8h 	; data port (3F8h, 2F8h)
	out	dx, al	   	; send on serial port
	; 17/11/2015
	cmp 	byte [edi], 0   ; query ? (schar)
	jne 	short com_i1    ; no
	mov	[edi], al 	; 0FFh (responded)
com_i1:
	; 17/11/2015
	; reset request for response status (again)
        dec     byte [ebx+req_resp-8] ; 0 
	jmp	short com_eoi
com_i2:	
	; 08/11/2015
	cmp 	al, 0FFh	; (response ?)
	je	short com_i3	; (check for response signal)
	; 07/11/2015
	cmp	al, 04h	; EOT
	jne	short com_i4	
	; EOT = 04h (End of Transmit) - 'CTRL + D'
	;(an EOT char is supposed as a ctrl+brk from the terminal)
	; 08/11/2015
		; ptty -> tty 0 to 7 (pseudo screens)
	xchg	bl, [ptty]  ; tty number (8 or 9)
	call 	ctrlbrk
	xchg	[ptty], bl ; (restore ptty value and BL value)
	;mov	al, 04h ; EOT
	; 08/11/2015
	jmp	short com_i4	
com_i3:
	; 08/11/2015
	; If 0FFh has been received just after a query
	; (schar, ZERO), it is a response signal.
	; 17/11/2015
        cmp     byte [edi], 0 ; query ? (schar)
	ja	short com_i4 ; no
	; reset query status (schar)
	mov	[edi], al ; 0FFh
	inc	al ; 0
com_i4:
	; 27/07/2014
	; 09/07/2014
	shl	bl, 1	
	add	ebx, ttychr
	; 23/07/2014 (always overwrite)
	;;cmp	word [ebx], 0
	;;ja	short com_eoi
	;
	mov	[ebx], ax   ; Save ascii code
			    ; scan code = 0
com_eoi:
	;mov	al, 20h
	;out	20h, al	   ; end of interrupt
	;
	; 07/11/2015
      	;pop	eax ; *
	mov	al, byte [ccomport] ; current COM port
	 ; al = tty number (8 or 9)
        call	wakeup
com_iret:
	; 23/10/2015
	pop	edx ; **
	pop	ecx ; ***
	; 18/11/2015
	;pop	eax ; ****
	;mov	cr3, eax
	;jmp	iiret
	jmp	iiretp

;iiretp: ; 01/09/2015
;	; 28/08/2015
;	pop	eax ; (*) page directory
;	mov	cr3, eax
;iiret:
;	; 22/08/2014
;	mov	al, 20h ; END OF INTERRUPT COMMAND TO 8259
;	out	20h, al	; 8259 PORT
;	;
;	pop	es
;	pop	ds
;	pop	edi
;	pop	esi
;	pop	ebx ; 29/08/2014
;	pop 	eax
;	iretd

sp_init:
	; 07/11/2015
	; 29/10/2015
	; 26/10/2015
	; 23/10/2015
	; 29/06/2015
	; 14/03/2015 (Retro UNIX 386 v1 - 115200 baud)
	; 28/07/2014 (Retro UNIX 8086 v1 - 9600 baud)
	; Initialization of Serial Port Communication Parameters
	; (COM1 base port address = 3F8h, COM1 Interrupt = IRQ 4)
	; (COM2 base port address = 2F8h, COM1 Interrupt = IRQ 3)
	;
	; ((Modified registers: EAX, ECX, EDX, EBX))
	;
	; INPUT:  (29/06/2015)
	;	AL = 0 for COM1
	;	     1 for COM2
	;	AH = Communication parameters	
	;
	;  (*) Communication parameters (except BAUD RATE):
	;	Bit	4	3	2	1	0
	;		-PARITY--   STOP BIT  -WORD LENGTH-	 		 
	;  this one -->	00 = none    0 = 1 bit  11 = 8 bits
	;		01 = odd     1 = 2 bits	10 = 7 bits
	;		11 = even
	;  Baud rate setting bits: (29/06/2015)
	;		Retro UNIX 386 v1 feature only !
	;	Bit	7    6    5  | Baud rate
	;		------------------------
	;	value	0    0    0  | Default (Divisor = 1)
	;		0    0    1  | 9600 (12)
	;		0    1    0  | 19200 (6) 
	;		0    1	  1  | 38400 (3) 
	;		1    0	  0  | 14400 (8)
	;		1    0	  1  | 28800 (4)
	;		1    1    0  | 57600 (2)
	;		1    1    1  | 115200 (1) 	
	
	; References:	
	; (1) IBM PC-XT Model 286 BIOS Source Code
	;     RS232.ASM --- 10/06/1985 COMMUNICATIONS BIOS (RS232)
	; (2) Award BIOS 1999 - ATORGS.ASM
	; (3) http://wiki.osdev.org/Serial_Ports
	;
	; Set communication parameters for COM1 (= 03h)	
	;
	mov	ebx, com1p		; COM1 parameters  
	mov	dx, 3F8h		; COM1
	 ; 29/10/2015
	mov	cx, 301h  ; divisor = 1 (115200 baud)
	call	sp_i3	; call A4	
	test	al, 80h
	jz	short sp_i0 ; OK..
		; Error !
	;mov	dx, 3F8h
	sub	dl, 5 ; 3FDh -> 3F8h
	mov	cx, 30Eh  ; divisor = 12 (9600 baud)
	call	sp_i3	; call A4	
	test	al, 80h
	jnz	short sp_i1
sp_i0:
        ; (Note: Serial port interrupts will be disabled here...)	
        ; (INT 14h initialization code disables interrupts.)
	;
	mov	byte [ebx], 0E3h ; 11100011b
	call	sp_i5 ; 29/06/2015
sp_i1:
	inc	ebx
	mov	dx, 2F8h		; COM2
	 ; 29/10/2015
	mov	cx, 301h  ; divisor = 1 (115200 baud)
	call	sp_i3	; call A4	
	test	al, 80h
	jz	short sp_i2 ; OK..
		; Error !
	;mov	dx, 2F8h
	sub	dl, 5 ; 2FDh -> 2F8h
	mov	cx, 30Eh  ; divisor = 12 (9600 baud)
	call	sp_i3	; call A4	
	test	al, 80h
	jnz	short sp_i7
sp_i2:
	mov	byte [ebx], 0E3h ; 11100011b
sp_i6:
	;; COM2 - enabling IRQ 3
	; 07/11/2015
	; 26/10/2015
	pushf
	cli
	;
	mov	dx, 2FCh   		; modem control register
	in	al, dx 	   		; read register
	JMP	$+2	   		; I/O DELAY
	or	al, 8      		; enable bit 3 (OUT2)
	out	dx, al     		; write back to register
	JMP	$+2	   		; I/O DELAY
	mov	dx, 2F9h   		; interrupt enable register
	in	al, dx     		; read register
	JMP	$+2	   		; I/O DELAY
	;or	al, 1      		; receiver data interrupt enable and
	or	al, 3	   		; transmitter empty interrupt enable
	out	dx, al 	   		; write back to register
	JMP	$+2        		; I/O DELAY
	in	al, 21h    		; read interrupt mask register
	JMP	$+2	   		; I/O DELAY
	and	al, 0F7h   		; enable IRQ 3 (COM2)
	out	21h, al    		; write back to register
	;
	; 23/10/2015
	mov 	eax, com2_int
	mov	[com2_irq3], eax
	; 26/10/2015
	popf	
sp_i7:
	retn

sp_i3:
;A4:  	;-----	INITIALIZE THE COMMUNICATIONS PORT
	; 28/10/2015
	inc	dl	; 3F9h (2F9h)	; 3F9h, COM1 Interrupt enable register 
	mov	al, 0
	out	dx, al			; disable serial port interrupt
	JMP	$+2			; I/O DELAY
	add	dl, 2 	; 3FBh (2FBh)	; COM1 Line control register (3FBh)
	mov	al, 80h			
	out	dx, al			; SET DLAB=1 ; divisor latch access bit
	;-----	SET BAUD RATE DIVISOR
	; 26/10/2015
	sub 	dl, 3   ; 3F8h (2F8h)	; register for least significant byte
					; of the divisor value
	mov	al, cl	; 1
	out	dx, al			; 1 = 115200 baud (Retro UNIX 386 v1)
					; 2 = 57600 baud
					; 3 = 38400 baud
					; 6 = 19200 baud
					; 12 = 9600 baud (Retro UNIX 8086 v1)
	JMP	$+2			; I/O DELAY
	sub	al, al
	inc	dl      ; 3F9h (2F9h)	; register for most significant byte
					; of the divisor value
	out	dx, al ; 0
	JMP	$+2			; I/O DELAY
	;	
	mov	al, ch ; 3		; 8 data bits, 1 stop bit, no parity
	;and	al, 1Fh ; Bits 0,1,2,3,4	
	add	dl, 2	; 3FBh (2FBh)	; Line control register
	out	dx, al			
	JMP	$+2			; I/O DELAY
	; 29/10/2015
	dec 	dl 	; 3FAh (2FAh)	; FIFO Control register (16550/16750)
	xor	al, al			; 0
	out	dx, al			; Disable FIFOs (reset to 8250 mode)
	JMP	$+2	
sp_i4:
;A18:	;-----	COMM PORT STATUS ROUTINE
	; 29/06/2015 (line status after modem status)
	add	dl, 4	; 3FEh (2FEh)	; Modem status register
sp_i4s:
	in	al, dx			; GET MODEM CONTROL STATUS
	JMP	$+2			; I/O DELAY
	mov	ah, al			; PUT IN (AH) FOR RETURN
	dec	dl	; 3FDh (2FDh)	; POINT TO LINE STATUS REGISTER
					; dx = 3FDh for COM1, 2FDh for COM2
	in	al, dx			; GET LINE CONTROL STATUS
	; AL = Line status, AH = Modem status
	retn

sp_status:
	; 29/06/2015
	; 27/06/2015 (Retro UNIX 386 v1)
	; Get serial port status
	mov	dx, 3FEh		; Modem status register (COM1)
	sub	dh, al			; dh = 2 for COM2 (al = 1)
					; dx = 2FEh for COM2
	jmp	short sp_i4s

sp_setp: ; Set serial port communication parameters
	; 07/11/2015
	; 29/10/2015
	; 29/06/2015
	; Retro UNIX 386 v1 feature only !	
	;
	; INPUT:
	;	AL = 0 for COM1
	;	     1 for COM2
	;	AH = Communication parameters (*)
	; OUTPUT:
	;	CL = Line status
	;	CH = Modem status
	;   If cf = 1 -> Error code in [u.error]
	;		 'invalid parameter !' 
	;		 	 or
	;		 'device not ready !' error
	;	
	;  (*) Communication parameters (except BAUD RATE):
	;	Bit	4	3	2	1	0
	;		-PARITY--   STOP BIT  -WORD LENGTH-	 		 
	;  this one -->	00 = none    0 = 1 bit  11 = 8 bits
	;		01 = odd     1 = 2 bits	10 = 7 bits
	;		11 = even
	;  Baud rate setting bits: (29/06/2015)
	;		Retro UNIX 386 v1 feature only !
	;	Bit	7    6    5  | Baud rate
	;		------------------------
	;	value	0    0    0  | Default (Divisor = 1)
	;		0    0    1  | 9600 (12)
	;		0    1    0  | 19200 (6) 
	;		0    1	  1  | 38400 (3) 
	;		1    0	  0  | 14400 (8)
	;		1    0	  1  | 28800 (4)
	;		1    1    0  | 57600 (2)
	;		1    1    1  | 115200 (1) 
	;
	; (COM1 base port address = 3F8h, COM1 Interrupt = IRQ 4)
	; (COM2 base port address = 2F8h, COM1 Interrupt = IRQ 3)
	;
	; ((Modified registers: EAX, ECX, EDX, EBX))
	;
	mov	dx, 3F8h
	mov	ebx, com1p ; COM1 control byte offset
	cmp	al, 1
	ja 	short sp_invp_err
	jb	short sp_setp1 ;  COM1 (AL = 0)
	dec	dh ; 2F8h
	inc	ebx ; COM2 control byte offset
sp_setp1:
	; 29/10/2015
	mov	[ebx], ah
	movzx 	ecx, ah
	shr	cl, 5 ; -> baud rate index
	and	ah, 1Fh ; communication parameters except baud rate
	mov	al, [ecx+b_div_tbl]
	mov	cx, ax
	call	sp_i3
	mov	cx, ax ; CL = Line status, CH = Modem status
	test	al, 80h
	jz	short sp_setp2
        mov     byte [ebx], 0E3h ; Reset to initial value (11100011b)
stp_dnr_err:
	mov	dword [u.error], ERR_DEV_NOT_RDY ; 'device not ready !'
	; CL = Line status, CH = Modem status
	stc
	retn
sp_setp2:
	cmp	dh, 2 ; COM2 (2F?h)
        jna     sp_i6 
		      ; COM1 (3F?h)
sp_i5: 
	; 07/11/2015
	; 26/10/2015
	; 29/06/2015
	;
	;; COM1 - enabling IRQ 4
	pushf
	cli
	mov	dx, 3FCh   		; modem control register
	in	al, dx 	   		; read register
	JMP	$+2			; I/O DELAY
	or	al, 8      		; enable bit 3 (OUT2)
	out	dx, al     		; write back to register
	JMP	$+2			; I/O DELAY
	mov	dx, 3F9h   		; interrupt enable register
	in	al, dx     		; read register
	JMP	$+2			; I/O DELAY
	;or	al, 1      		; receiver data interrupt enable and
	or	al, 3	   		; transmitter empty interrupt enable
	out	dx, al 	   		; write back to register
	JMP	$+2        		; I/O DELAY
	in	al, 21h    		; read interrupt mask register
	JMP	$+2			; I/O DELAY
	and	al, 0EFh   		; enable IRQ 4 (COM1)
	out	21h, al    		; write back to register
	;
	; 23/10/2015
	mov 	eax, com1_int
	mov	[com1_irq4], eax
	; 26/10/2015
	popf
	retn

sp_invp_err:
	mov	dword [u.error], ERR_INV_PARAMETER ; 'invalid parameter !' 
	xor	ecx, ecx
	dec	ecx ; 0FFFFh
	stc
	retn

; 29/10/2015
b_div_tbl: ; Baud rate divisor table (115200/divisor)
	db 1, 12, 6, 3, 8, 4, 1


; 23/10/2015
com1_irq4:
	dd dummy_retn
com2_irq3:
	dd dummy_retn

dummy_retn:
	retn

wakeup:
	; 24/01/2016
	retn
