; UNIX.ASM (RETRO UNIX 8086 Kernel - Only for 1.44 MB floppy disks)
; ----------------------------------------------------------------------------
; U0.ASM (include u0.asm) //// UNIX v1 -> u0.s

; RETRO UNIX 8086 (Retro Unix == Turkish Rational Unix)
; Operating System Project (v0.1) by ERDOGAN TAN (Beginning: 11/07/2012) 
; 1.44 MB Floppy Disk 
; (11/03/2013)
;
; [ Last Modification: 18/01/2014 ] ;;; completed ;;;
;
; Derivation from UNIX Operating System (v1.0 for PDP-11) 
; (Original) Source Code by Ken Thompson (1971-1972)
; <Bell Laboratories (17/3/1972)>
; <Preliminary Release of UNIX Implementation Document>
;
; ****************************************************************************

; 17/01/2014
; 30/10/2013, 04/12/2013, 06/12/2013, 10/12/2013
; 24/09/2013, 29/09/2013, 05/10/2013, 10/10/2013	
; 30/08/2013, 03/09/2013, 17/09/2013, 20/09/2013
; 23/07/2013, 29/07/2013, 11/08/2013, 12/08/2013	
; 16/07/2013, 17/07/2013, 18/07/2013, 22/07/2013
; 15/07/2013, 20/05/2013, 21/05/2013, 27/05/2013
; 15/05/2013, 17/05/2013, 13/07/2013, 14/07/2013
; 11/03/2013, 11/04/2013, 09/05/2013, 10/05/2013

kernel_init:
	; 04/12/2013
	; 05/10/2013
	; 29/07/2013
	; 18/07/2013
	; 17/07/2013
	; 14/07/2013
	; 13/07/2013
	; Retro UNIX 8086 v1 feature only !
	;
	; Retro UNIX 8086 v1 
	; kernel relies on data from its 'boot' program ...
	;
	;;mov 	ax, cs
	;mov 	ds, ax
	;mov 	es, ax
	;cli
	;mov 	ss, ax
	;mov 	sp, 32766 
	;sti
	; mov 	bp, sp
	mov     byte ptr [unixbootdrive], dl
	mov	ds, cx ; boot sector segment
 	; bx = boot sector buffer
	mov	ax, word ptr [BX]+2 ; 14/07/2013
	mov	dx, word ptr [BX]+4 ; 14/07/2013
	push	cs
	pop	ds
	cmp	ax, 'UR'
	jne	kernel_init_err ; jne short kernel_init_err
	cmp	dx, 'SF'
	jne	kernel_init_err ; jne short kernel_init_err
	;
	call	drv_init
	jc      kernel_init_err ; jne short kernel_init_err
	;
	mov	al, time_count ; 30/08/2013
	;; 29/07/2013
	;;mov	byte ptr [s.wait_]+2, al
        ;;mov     byte ptr [s.idlet]+2, al
	mov	byte ptr [uquant], al ; 14/07/2013
	; 22/07/2013
	mov	ax, cs
	mov	word ptr [u.segmnt], ax ; reset to CS
        ;
 	call	epoch
	mov	word ptr [s.time], ax
	mov	word ptr [s.time]+2, dx
	;
	call	kb_init
	;
	;; 10/12/2013 
	;; INT 1Ch handling disabled here,
	;;	it will be enabled by 'sys emt'
	;;	system call (in 'etc/init')
; INT 1Ch (clock/timer) transfer to unix kernel
	xor 	ax, ax
	mov 	es, ax ; 0
	;;mov 	di, 28*4 ; INT 1Ch vector - offset
	;;cli
	;;mov	ax, offset clock
	;;stosw   ; offset
	;;mov	ax, cs
	;stosw	; segment
	;;sti
	;
; setting up syscall vector (int 20h)
	mov	ax, offset sysent
	mov	di, 32*4 ; INT 20h for system calls
	stosw
	mov	ax, cs
	stosw
	mov	es, ax
	;
	;
;;	13/07/2013
;,	Kernel is running message ... (temporary)
;
	mov	si, offset kernel_init_ok_msg
	call 	print_msg
	; 17/01/2014
	call	sp_init ; serial port interrupts
	; 
	; 05/10/2013 Temporary
	xor 	al, al ; mov al, 0
	call	getc
	; 16/07/2013
	;xor 	al, al
	; 04/12/2013
	xor	bl, bl ; video page 0
@@:	; clear video pages (reset cursor positions)
	call 	vp_clr  ; 17/07/2013
	inc	bl
	cmp	bl, 8
	jb	short @b
	;
	;
	; 14/07/2013
	mov	ax, 41
	mov	word ptr [rootdir], ax
	mov	word ptr [u.cdir], ax
	mov	al, 1
	mov	byte ptr [u.uno], al
	mov	word ptr [mpid], ax
	mov	word ptr [p.pid], ax
	mov	byte ptr [p.stat], al 
	; 17/07/2013
	;mov    al, byte ptr [unixbootdrive]
	;cmp	al, 80h ; 128 (80h->hd0)
	;jna	short @f
	;sub	al, 7Eh ; 126 (2->hd0)
;@@:
	;mov	byte ptr [rdev], al
	;
	call 	bf_init ; buffer initialization ; 17/07/2013			
;;
;; original UNIX v1 (PDP-11) code here:
	; / make current program a user
	;
	; mov    $41.,r0 / rootdir set to 41 and never changed
	; mov    r0,rootdir / rootdir is i-number of root directory
	; mov    r0,u.cdir / u.cdir is i-number of process current directory
	; mov    $1,r0
	; movb   r0,u.uno / set process table index for this process to 1
	; mov    r0,mpid / initialize mpid to 1
	; mov    r0,p.pid / p.pid identifies process
	; movb   r0,p.stat / process status = 1 i.e., active
        ;                 /                = 0 free
	;                 /                = 2 waiting for a child to die
        ;                 /                = 3 terminated but not yet waited
        ;                 /                  for
	; 18/01/2014
	;sti
	; 24/07/2013
	mov	bx, offset init_file
	mov	cx, offset init_argp
	; (([u.segmnt] = CS))
	; BX contains 'etc/init' asciiz file name address  
	; CX contains address of argument list pointer
	;
	dec 	byte ptr [sysflg] ; FFh = ready for system call
			      	  ; 0 = executing a system call
	;mov	ax, _exec
	;int	20h
	sys	_exec  ; execute file
	;
	jnc	short panic
	;
	mov	si, offset etc_init_err_msg
	jmp	short @f

;; original UNIX v1 (PDP-11) code here:
 ; 1:
	; decb sysflg / normally sysflag=0, indicates executing in system
	; sys exec; 2f; 1f / generates trap interrupt; trap vector =
        ;                  / sysent; 0
	; br  panic / execute file/etc/init

 ; 1:
	; 2f;0
 ; 2:
	; </etc/init\0> / UNIX looks for strings term, noted by nul\0

kernel_init_err:
	;; NOTE: UNix kernel will load boot sector
	;; 	
	mov	si, offset kernel_init_err_msg
@@:
	call 	print_msg
	jmp	short key_to_reboot

align 2
init_argp:
	dw 	offset init_file, 0
init_file:
	db 	'/etc/init', 0

panic:
	; 05/10/2013 ('call getc' instead of 'int 16h')
	; 14/07/2013 (panic_msg/print_msg)
      	; 10/04/2013	
      	;
      	; Retro Unix 8086 v1 modification on original Unix v1 panic procedure!
      	;
	
	mov si, offset panic_msg
	call print_msg
key_to_reboot:
	;hlt
	; 05/10/2013
	xor al, al
	call getc
	; 
	; 15/07/2013
	mov 	ah, 0Eh
	;mov 	bx, 07h
	;mov 	al, 0Dh
	;int 	10h
 	mov 	al, 0Ah
	int 10h			
;@@:
	; 24/09/2013
	; Reset INT 09h vector for next start-up
	xor di, di
	mov es, di
	mov di, 4*9
	mov si, offset int09h
	movsw
	movsw		
	;
      	int 19h

;      	hlt	
;      	jmp short @b  			
	
	; clr ps
;1:
	; dec $0
	; bne 1b
	; dec $5
	; bne 1b
	; jmp *$173700 / rom loader address

print_msg:
	; 14/07/2013
	; 13/07/2013
	lodsb
	mov	bx, 07h
	mov	ah, 0Eh
@@:
	int	10h
	lodsb
	and	al, al
	jnz	short @b
	retn

kb_init:
	; 11/08/2013
	; 16/07/2013
	; 15/07/2013
	; 13/07/2013
	; 21/05/2013 
	; 17/05/2013
	; 10/05/2013	
      	;
	; Initialization of keyboard handlers		
	;
      	; Retro Unix 8086 v1 feature only!
      	;
	; ((Modified registers: AX, CX, SI, DI))

	;xor 	al, al
	;mov	byte ptr [ptty], al ; 0
	;mov	byte ptr [nxtty], al ; 0
	;call 	tty_clr
@@:
	xor 	ax, ax ; 11/08/2013
	mov	di, offset int09h
	mov 	ds, ax ; 0
	mov	ax, 9*4 ; INT 09h vector - offset
	mov	si, ax
	movsw		; offset
	movsw		; segment
	mov	di, ax
	mov	ax, ds
	mov	es, ax	
	mov	ax, cs
	mov	ds, ax
	cli
	mov	ax, offset kb_int
	stosw		
	mov	ax, cs
	stosw		
	mov	ax, offset ctrlbrk
	mov	di, 27*4 ; INT 1Bh vector - offset
	stosw		; offset
	mov	ax, cs
	stosw		; segment
	sti
	mov	es, ax
	; 16/07/2013
	jmp	short tty_clr

ctrlbrk:
	; 06/12/2013
	; 20/09/2013
	; 03/09/2013
    	; 09/05/2013	
      	;
	; INT 1Bh (control+break) handler		
	;
      	; Retro Unix 8086 v1 feature only!
      	;
	cmp 	word ptr CS:[u.intr], 0
	ja 	short cbrk1
	iret
cbrk1:
	; 20/09/2013	
	push 	ax
	mov	al, byte ptr CS:[ptty]
	inc 	al
	; 06/12/2013
	cmp	al, byte ptr CS:[u.ttyp]
	je	short cbrk2	
	cmp	al, byte ptr CS:[u.ttyp]+1
	jne	short cbrk3	
cbrk2:
	; 06/12/2013
	mov	ax, word ptr CS:[u.quit]
	and	ax, ax
	jz	short cbrk3
	xor	ax, ax ; 0
	dec	ax
	; 0FFFFh = 'ctrl+brk' keystroke
	mov	word ptr CS:[u.quit], ax
cbrk3:
	pop	ax
	iret


tty_sw: ; < tty switch >
	; 04/12/2013 'act_disp_page' (U9.ASM)
	; 29/09/2013 (simplified)
	; 29/09/2013 u1.asm -> u0.asm
	; 22/09/2013
	; 17/09/2013
	; 03/09/2013
	; 21/08/2013
	; 18/08/2013
	; 16/07/2013
	; 15/07/2013
	; 20/05/2013
	;
	; Retro UNIX 8086 v1 feature only !
	;
	; INPUTS:
	;   AL = tty number to be switched on
	; OUTPUTS:
	;   Keyboard buffer will be reset and 
	;   active video page will be changed
	;   according to the requested tty number.
	;
	; ((Modified registers: AX))  
	;
	; 29/09/2013
	; 03/09/2013
	;
	;mov	al, byte ptr [nxtty] ; tty number
	;	                     ; video page
	;;; 
	; 04/12/2013
	;mov	ah, 5 ; Set video page
	;int 	10h
	;mov	byte ptr [ptty], al ; byte ptr [active_page], al
	call 	act_disp_page
	;;;
	;
	;;jmp 	short	tty_clr ; clear/reset keyboard buffer

tty_clr: 
	; Reset/Clear keyboard/tty buffer
	;
	; 18/01/2014 (pushf, cli, popf)
	; 29/09/2013 (push si, pop si)
	; 16/07/2013 
	;
	; Retro UNIX 8086 v1 feature only !
	;
	; INPUTS -> 
	;    none
	;
	; OUTPUT ->
	;   none
	; ((Modified registers: AX))
	; ((DS = CS))
	;
	push 	si ; 29/09/2013
	mov	ax, 40h
	mov	ds, ax
	mov	si, headptr
	pushf		
	cli
	lodsw 	; headptr -> ax
	mov	word ptr [SI], ax ; tailptr
	mov	si, 17h
	mov	ax, word ptr [SI]
	and	ax, 0F0h ; clear all flags
			; except
			; caps-lock, scroll-lock
			; num-lock and insert 
			; status bits 
	mov	word ptr [SI], ax
	;
	popf
	mov	ax, cs
	mov	ds, ax
	pop	si ; 29/09/2013	
	retn

kb_int:
	; INT 09h Keyboard Handler		
	;
	; 18/01/2014
	; 17/01/2014
        ; 10/10/2013   
	; 05/10/2013
	; 29/09/2013
	; 24/09/2013
	; 03/09/2013
	; 12/08/2013
	; 11/08/2013
	; 20/05/2013
	; 15/05/2013 
    	; 10/05/2013	
      	;
	; Retro Unix 8086 v1 feature only!

	push	ds
	push	ax
	;
	; 24/09/2013
	push	bx
	;
	; 05/10/2013
	mov	ax, cs
	mov	ds, ax
	;
	; 18/01/2014
	; beeper -> sti :: (waitf)
	mov	al, byte ptr [kb_int_f]
	inc	byte ptr [kb_int_f]
	and 	al, al
	jnz	short kb_int_rpt
	;
	xor	bh, bh
	mov	bl, byte ptr [ptty]
	;
	push	cx
	xor 	cx, cx
kb_int_0:
	in	al, 64h
	test	al, 2 ; Bit 1, input buffer full ?
	loopnz	kb_int_0
	pop	cx
	;
	in      al, 60h                 ; Read the scan code
        cmp     al, 38h			; 'Alt' key down
	jne	short kb_int_1
	mov	byte ptr [AltKeyDown], 1
	jmp	short kb_int_3
kb_int_1:	
	cmp	al, 38h+80h		; 'Alt' key up
	jne	short kb_int_2
	mov	byte ptr [AltKeyDown], 0
	jmp	short kb_int_3
kb_int_2:
	cmp	byte ptr [AltKeyDown], 0
	jna	short kb_int_3
	;
        cmp     al, 3Bh                 ; Alt + F1
	jb	short kb_int_3
        ;cmp    al, 44h                 ; Alt + F10
	;ja	short kb_int_3
        cmp     al, 42h                 ; Alt + F8                          
	ja	short kb_int_3
	; 03/09/2013
       	;add     al, 68h-3Bh
	;mov	ah, al 
       	;sub     ah, 68h
	;mov	byte ptr [nxtty], ah	; next tty number
	sub 	al, 3Bh
	; 24/09/2013
	cmp	al, bl ; byte ptr [ptty]
	;cmp	ah, bl ; byte ptr [ptty]
	je 	short kb_int_3
	call 	tty_sw
	; 29/09/2013
	; Following code copied from...
	; http://webpages.charter.net/danrollins/techhelp/0106.HTM
	; (originally written by Dan Rollins)
	; "INT 09h - Keyboard Interrrupt"
	;
	;;following housekeeping is needed to satisfy the hdwr int
 	;
kb_int_rpt:
	in      al, 61h		;get value of keyboard control lines
        mov     ah, al 		; save it
        or      al, 80h		;set the "enable kbd" bit
        out     61h, al		; and write it out the control port
        ;xchg    ah, al		;
       	mov	al, ah		;fetch the original control port value
	out     61h, al		; and write it back
				;
        mov     al, 20h		;send End-Of-Interrupt signal
        out     20h, al		; to the 8259 Interrupt Controller
	;
	; 29/09/2013
	jmp 	short kb_int_5
kb_int_3:
	pushf
	call 	dword ptr [int09h]	; Call BIOS INT 09h handler
	; 24/09/2013
	mov	ah, 1
	int 	16h
	jz	short kb_int_5
	xor	ah, ah
	int 	16h
	shl	bl, 1
	add	bx, offset ttychr
	; 29/09/2013
	cmp 	word ptr [BX], 0
	jna	short kb_int_4
	mov 	al, 07h
	mov	ah, 0Eh	
	;;mov	bl, 7
	;int	10h
	; 17/01/2014
	call	beeper	; 'beep' sound
	jmp	short kb_int_5
kb_int_4:
	; 24/09/2013
	mov	word ptr [BX], ax  ; Save ascii code
				   ; and scan code of the character
				   ; for current tty (or last tty
				   ; just before tty switch).
        ; 10/10/2013
        mov     al, byte ptr [ptty]
	mov	bx, offset runq
	call	wakeup
	;
kb_int_5:
	; 18/01/2014
	dec	byte ptr [kb_int_f]
	;	
	pop	bx ; 24/09/2013
	pop	ax
	pop	ds
	iret

vp_clr:
	; Reset/Clear Video Page
	;
	; 04/12/2013 scroll_up (U9.ASM) 
	;
	; 30/10/2013
	; 17/09/2013
	; 17/07/2013
	; 21/05/2013
	;
	; Retro UNIX 8086 v1 feature only !
	;
	; INPUTS -> 
	;   AL = video page number	 
	;
	; OUTPUT ->
	;   none
	; ((Modified registers: AX, BH, CX, DX, SI, DI))
	;
	; 04/12/2013
	sub	al, al
	; al = 0 (clear video page)
	; bl = video page
	mov	bh, 07h
	; bh = 7 (attribute/color)
	call	scroll_up
	; bh = 7
	; bl = video page
	xor	dx, dx ; 0
	;call	set_cpos
	;retn
	
	jmp 	set_cpos	
	
	; 30/10/2013
	;push	es
	;xor	ah, ah
	;;push	ax
	;mov	di, 0B800h
	;mov	es, di
	;mov	cx, 2000
	;sub	dx, dx ; 30/10/2013
	;or 	al, al
	;jz	short @f
 	;; 30/10/2013
	;shl	al, 1
	;; 17/09/2013
	;push 	ax
	;mul	cx
	;pop	dx
 ;@@:
	;mov	di, ax ; 17/09/2013
	;mov	ah, 07h ; color
	;rep	stosw
	;;pop	ax
	;;mov	bh, al ; video page
	;;mov	ah, 2 ; set cursor position
	;;xor 	dx, dx
	;;int 	10h
	;;xor 	ax, ax
	;xor	ah, ah
	;;pop	di    ; Video page number
	;;shl	di, 1
	;mov	di, dx
	;mov	es, ax ; 0
	;add	di, 450h ; 40h:50h or 0h:450h
	;; di = cursor position of the video page.
	;stosw	; reset cursor position
	;pop 	es	
	;retn


com1_int:
	; 17/01/2014
	; < serial port 1 interrupt handler >
	push	ax
	mov	ah, 8 ; ttyy number of COM1
@@:
	push	bx
	push	ds
	push	cs
	pop	ds	
	mov 	bx, offset runq + 2 ; middle priority
	call 	wakeup
	pop	ds
	pop	bx
	;
	pop	ax
	iret
		
com2_int:
	; 17/01/2014
	; < serial port 2 interrupt handler >
	push	ax
	mov	ah, 9	; tty number of com2
	jmp	short @b

sp_init:
	; 17/01/2014
      	;
	; Initialization of serail port interrupt handlers		
	;
      	; Retro Unix 8086 v1 feature only!
      	;
	; ((Modified registers: AX, DI))

	mov	di, 0Bh * 4  ; COM 2 (IRQ 3) interrupt vector
 	cli
	mov	ax, offset com2_int
	stosw		
	mov	ax, cs
	stosw
	mov	ax, offset com1_int
	;mov	di, 0Ch * 4  ; COM 1 (IRQ 4) interrupt vector
	stosw
	mov	ax, cs
	stosw
	sti
	retn
