/*
    video.S, Copyright  (c) by Lukas Ruf, lr@lpr.ch,
    Swiss Federal Institute of Technology,
    Computer Engineering and Networks Laboratory.

    TOPSY -- A Teachable Operating System.
         Implementation of a tiny and simple
         micro kernel for teaching purposes.

    For further information, please visit http://www.tik.ee.ethz.ch/~topsy

    This software is provided under the terms of the GNU General Public Licence.

    A full copy of the GNU GPL is provided in the file COPYING found in the 
    development root of Topsy.
*/
/*
    File:                  $Source: /home/ruf/cvs_Topsy/cvs/Topsy/IO/ia32/Drivers/video.S,v $
    Author(s):             Lukas Ruf, lr@lpr.ch
    Affiliation:           ETH Zuerich, TIK
    Version:               $Revision: 2994 $
    Creation Date:         
    Last Date of Change:   $Date: 2007-03-30 22:30:57 +0200 (Fre, 30 Mär 2007) $      by: $Author: sryffel $
*/
.section .sasm
.align 4,0x9090

#include "MemoryLayout.h"

#include "asm.h"                /* Assembler Macros :-) */
                                /* Topsy/i386/          */

#define CRTCPort1   0x03D4   /* Index port for CRTC */
#define CRTCPort2   0x03D5   /* Data port for CRTC */
#define CRTCCurHi   0x0E     /* Register for hi byte of Cursor address */
#define CRTCCurLo   0x0F     /* Register for lo byte of Cursor address */

//
//void Printchar(uint XYPos, uchar TextAttr, char uc);
//
ASM_PROC_FRAME(__printchar)
        ENTER
        /* we are in ring 0, there it is allowed :- */
        pushfl  
        cli
        
        pushl   %eax
        pushl   %es
        pushl   %edi
        
        movl    $GC_VIDEO_SEL,%eax        // video selector
        movw    %ax,%es
        movl    ARG1,%eax    // XYPos
        movl    %eax,%edi

        movl    ARG3,%eax   // char al = uc
        stosb                   // = movw %ax,%es:[%edi]
        movl    ARG2,%eax   // char al = TextAttr
        stosb
        
        popl    %edi
        popl    %es
        popl    %eax
        
        popfl
        
        LEAVE
        
////
// _printstr(ulong pXYOffs, uchar pAttr, uchar *pstr); 
////
ASM_PROC_FRAME(__printstr)
        ENTER
        
        pushfl
        cli
        
        pushl   %eax
        pushl   %edi
        pushl   %esi
        pushl   %es

        movl    $GC_VIDEO_SEL,%eax
        movw    %ax,%es

        movl    ARG1,%edi       
        movl    ARG2,%eax
        movl    ARG3,%esi
        movb    %al,%ah         // store attr. in %ah
        cld
    _pl1:
        lodsb
        orb     %al,%al
        jz      _pl2
        stosb
        movb    %ah,%al
        stosb
        jmp     _pl1
    _pl2:       
    
        popl    %es
        popl    %esi
        popl    %edi
        popl    %eax
        
        popfl   
        
        LEAVE
        
////
// _scrollup(uchar pTextAttr);
////

ASM_PROC_FRAME(__scrollup)
        ENTER
        
        pushfl
        cli
        
        pushl   %eax
        pushl   %ecx
        pushl   %edi
        pushl   %esi
        pushl   %ds
        pushl   %es
        
        movl    $GC_VIDEO_SEL,%eax
        movw    %ax,%ds
        movw    %ax,%es
        
        movl    $920,%ecx               // (4000-160-160)/4  
        xorl    %edi,%edi
        movl    $160,%esi               // 160 / 4 : letzte Zeile
        repnz   
        movsl
        
        movl    ARG1,%eax
        xchgb   %al,%ah
        movw    %ax,%cx
        shll    $16,%ecx
        orl     %ecx,%eax
        
        movl    $40,%ecx                // 160 / 4 : letzte Zeile
        rep     
        stosl
        
        popl    %es
        popl    %ds
        popl    %esi
        popl    %edi
        popl    %ecx
        popl    %eax

        popfl
        
        LEAVE

////
// void _moveVideoLine(ulong pDest, ulong pSource, ulong pWordCounter);
ASM_PROC_FRAME(__moveVideoLine)
        ENTER
//-LR         LEAVE

        pushfl
        pushl   %eax
        pushl   %ecx
        pushl   %edi
        pushl   %esi
        pushl   %ds
        pushl   %es

        movl    $GC_VIDEO_SEL,%eax
        movw    %ax,%ds
        movw    %ax,%es
        
        movl    ARG1,%eax
        movl    %eax,%edi
        movl    ARG2,%eax
        movl    %eax,%esi
        cld
        movl    ARG3,%ecx
        rep
        movsw
        
        popl    %es
        popl    %ds
        popl    %esi
        popl    %edi
        popl    %ecx
        popl    %eax
        popfl   

        LEAVE
////
//void _clearLine(ulong pLeft, uchar pHCountr, uchar pAttr);
ASM_PROC_FRAME(__clearLine)
        ENTER

        pushfl
        pushl   %eax
        pushl   %ecx
        pushl   %edi
        push    %es

        movl    $GC_VIDEO_SEL,%eax
        movw    %ax,%es
        
        movl    ARG1,%eax
        movl    %eax,%edi
        movl    ARG2,%ecx
        movl   	ARG3,%eax
        xchgb   %al,%ah
        cld
        rep 
        stosw
        
        pop     %es
        popl    %edi
        popl    %ecx
        popl    %eax
	popfl

        LEAVE
        
////
// void _scrollWindowUp(ulong pTopLeft, uchar pVCounter, uchar pHCounter, 
//                      uchar pAttr);
ASM_PROC_FRAME(__scrollWindowUp)
        ENTER
	
        pushl   %eax
        pushl   %ebx
        pushl   %ecx
        pushl   %edx

        movl    ARG1,%eax   // TopLeftCorner (Offset into V-RAM)
        movl    ARG2,%ecx   // pVCounter (Vertical)
        movl    ARG3,%edx   // pHCounter (Horizontal)
_sWUL1: 
        pushl   %edx
        movl    %eax,%ebx
        addl    $160,%eax
        pushl   %eax
        pushl   %ebx
        call    __moveVideoLine
        addl    $12,%esp
        loop    _sWUL1
        
        // %eax points to beginning of last line
        movl    ARG4,%ebx   // pAttr
        pushl   %ebx            // pAttr
        pushl   %edx            // pHCounter
        pushl   %eax
        call    __clearLine
        addl    $12,%esp
        
        popl    %edx
        popl    %ecx
        popl    %ebx
        popl    %eax
     
     	LEAVE
        
////
// void _getWindowLine(char *pBuff, ulong pLeftTop, ulong pWordCount);
ASM_PROC_FRAME(__getWindowLine)
        ENTER

        pushfl
        pushl   %ecx
        pushl   %edi
        pushl   %esi
        pushl   %ds
        
        movl    $GC_VIDEO_SEL,%ecx
        movw    %cx,%ds
        movl    ARG1,%edi
        movl    ARG2,%esi
        movl    ARG3,%ecx
        cld
        rep
        movsw
        
        popl    %ds
        popl    %esi
        popl    %edi
        popl    %ecx
        popfl

	LEAVE
        
////
// void _setWindowLine(char *pBuff, ulong pLeftTop, ulong pWordCount);
ASM_PROC_FRAME(__setWindowLine)
        ENTER

        pushfl
        pushl   %eax
        pushl   %ecx
        pushl   %edi
        pushl   %esi
        pushl   %es
        
        movl    $GC_VIDEO_SEL,%eax
        movw    %ax,%es
        movl    ARG2,%eax
        movl    %eax,%edi
        movl    ARG1,%eax
        movl    %eax,%esi
        movl    ARG3,%ecx
        cld
        rep
        movsw
        
        popl    %es
        popl    %esi
        popl    %edi
        popl    %ecx
        popl    %eax
        popfl
        
        LEAVE
	
/////
// void __setCursor(ulong pPosition);
////
ASM_PROC_FRAME(__setCursor)
	ENTER
	pushl	%eax
	pushl	%ebx
	pushl	%edx
	
	movl	ARG1,%ebx
	movl	$CRTCPort1,%edx
	movb	$CRTCCurLo,%al
	outb	%al,%dx
	movl	$CRTCPort2,%edx
	movl	%ebx,%eax
	outb	%al,%dx
	
	shrb	$8,%ebx	
	movl	$CRTCPort1,%edx
	movb	$CRTCCurHi,%al
	outb	%al,%dx
	movl	$CRTCPort2,%edx
	movl	%ebx,%eax
	outb	%al,%dx
	
	popl	%edx
	popl	%ebx
	popl	%eax
    	LEAVE	
	
