Changeset cefb126 in mainline for kernel/arch/ia32/src/asm.S


Ignore:
Timestamp:
2010-07-02T14:19:30Z (14 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
89c57b6
Parents:
fe7abd0 (diff), e3ee9b9 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge mainline changes.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/arch/ia32/src/asm.S

    rfe7abd0 rcefb126  
    1 #
    2 # Copyright (c) 2001-2004 Jakub Jermar
    3 # All rights reserved.
    4 #
    5 # Redistribution and use in source and binary forms, with or without
    6 # modification, are permitted provided that the following conditions
    7 # are met:
    8 #
    9 # - Redistributions of source code must retain the above copyright
    10 #   notice, this list of conditions and the following disclaimer.
    11 # - Redistributions in binary form must reproduce the above copyright
    12 #   notice, this list of conditions and the following disclaimer in the
    13 #   documentation and/or other materials provided with the distribution.
    14 # - The name of the author may not be used to endorse or promote products
    15 #   derived from this software without specific prior written permission.
    16 #
    17 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
    18 # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
    19 # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
    20 # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
    21 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
    22 # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    23 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    24 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    25 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    26 # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    27 #
    28 
    29 ## very low and hardware-level functions
    30 
    31 # Mask for interrupts 0 - 31 (bits 0 - 31) where 0 means that int has no error
    32 # word and 1 means interrupt with error word
    33 #define ERROR_WORD_INTERRUPT_LIST 0x00027d00
     1/*
     2 * Copyright (c) 2001 Jakub Jermar
     3 * All rights reserved.
     4 *
     5 * Redistribution and use in source and binary forms, with or without
     6 * modification, are permitted provided that the following conditions
     7 * are met:
     8 *
     9 * - Redistributions of source code must retain the above copyright
     10 *   notice, this list of conditions and the following disclaimer.
     11 * - Redistributions in binary form must reproduce the above copyright
     12 *   notice, this list of conditions and the following disclaimer in the
     13 *   documentation and/or other materials provided with the distribution.
     14 * - The name of the author may not be used to endorse or promote products
     15 *   derived from this software without specific prior written permission.
     16 *
     17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 */
     28
     29/** Very low and hardware-level functions
     30 *
     31 */
     32
     33/**
     34 * Mask for interrupts 0 - 31 (bits 0 - 31) where 0 means that int
     35 * has no error word  and 1 means interrupt with error word
     36 *
     37 */
     38#define ERROR_WORD_INTERRUPT_LIST  0x00027d00
     39
     40#include <arch/pm.h>
     41#include <arch/mm/page.h>
    3442
    3543.text
    36 
    3744.global paging_on
    3845.global enable_l_apic_in_msr
     
    4552.global memcpy_to_uspace
    4653.global memcpy_to_uspace_failover_address
    47 
    48 
    49 # Wrapper for generic memsetb
     54.global early_putchar
     55
     56/* Wrapper for generic memsetb */
    5057memsetb:
    5158        jmp _memsetb
    5259
    53 # Wrapper for generic memsetw
     60/* Wrapper for generic memsetw */
    5461memsetw:
    5562        jmp _memsetw
    5663
    57 
    58 #define MEMCPY_DST      4
    59 #define MEMCPY_SRC      8
    60 #define MEMCPY_SIZE     12
     64#define MEMCPY_DST   4
     65#define MEMCPY_SRC   8
     66#define MEMCPY_SIZE  12
    6167
    6268/** Copy memory to/from userspace.
     
    6874 * or copy_to_uspace().
    6975 *
    70  * @param MEMCPY_DST(%esp)      Destination address.
    71  * @param MEMCPY_SRC(%esp)      Source address.
    72  * @param MEMCPY_SIZE(%esp)     Size.
     76 * @param MEMCPY_DST(%esp)  Destination address.
     77 * @param MEMCPY_SRC(%esp)  Source address.
     78 * @param MEMCPY_SIZE(%esp) Size.
    7379 *
    7480 * @return MEMCPY_DST(%esp) on success and 0 on failure.
     81 *
    7582 */
    7683memcpy:
    7784memcpy_from_uspace:
    7885memcpy_to_uspace:
    79         movl %edi, %edx                 /* save %edi */
    80         movl %esi, %eax                 /* save %esi */
     86        movl %edi, %edx  /* save %edi */
     87        movl %esi, %eax  /* save %esi */
    8188       
    8289        movl MEMCPY_SIZE(%esp), %ecx
    83         shrl $2, %ecx                   /* size / 4 */
     90        shrl $2, %ecx  /* size / 4 */
    8491       
    8592        movl MEMCPY_DST(%esp), %edi
    8693        movl MEMCPY_SRC(%esp), %esi
    8794       
    88         rep movsl                       /* copy whole words */
    89 
     95        /* Copy whole words */
     96        rep movsl
     97       
    9098        movl MEMCPY_SIZE(%esp), %ecx
    91         andl $3, %ecx                   /* size % 4 */
     99        andl $3, %ecx  /* size % 4 */
    92100        jz 0f
    93101       
    94         rep movsb                       /* copy the rest byte by byte */
    95 
    96 0:
    97         movl %edx, %edi
    98         movl %eax, %esi
    99         movl MEMCPY_DST(%esp), %eax     /* MEMCPY_DST(%esp), success */
    100         ret
    101        
     102        /* Copy the rest byte by byte */
     103        rep movsb
     104       
     105        0:
     106       
     107                movl %edx, %edi
     108                movl %eax, %esi
     109               
     110                /* MEMCPY_DST(%esp), success */
     111                movl MEMCPY_DST(%esp), %eax
     112                ret
     113
    102114/*
    103115 * We got here from as_page_fault() after the memory operations
     
    108120        movl %edx, %edi
    109121        movl %eax, %esi
    110         xorl %eax, %eax                 /* return 0, failure */
     122       
     123        /* Return 0, failure */
     124        xorl %eax, %eax
    111125        ret
    112126
    113 ## Turn paging on
    114 #
    115 # Enable paging and write-back caching in CR0.
    116 #
     127/** Turn paging on
     128 *
     129 * Enable paging and write-back caching in CR0.
     130 *
     131 */
    117132paging_on:
    118133        movl %cr0, %edx
    119         orl $(1 << 31), %edx            # paging on
    120         # clear Cache Disable and not Write Though
     134        orl $(1 << 31), %edx  /* paging on */
     135       
     136        /* Clear Cache Disable and not Write Though */
    121137        andl $~((1 << 30) | (1 << 29)), %edx
    122         movl %edx,%cr0
     138        movl %edx, %cr0
    123139        jmp 0f
    124 0:
    125         ret
    126 
    127 
    128 ## Enable local APIC
    129 #
    130 # Enable local APIC in MSR.
    131 #
     140       
     141        0:
     142                ret
     143
     144/** Enable local APIC
     145 *
     146 * Enable local APIC in MSR.
     147 *
     148 */
    132149enable_l_apic_in_msr:
    133150        movl $0x1b, %ecx
     
    138155        ret
    139156
    140 # Clear nested flag
    141 # overwrites %ecx
     157/** Clear nested flag
     158 *
     159 */
    142160.macro CLEAR_NT_FLAG
    143161        pushfl
    144         pop %ecx
    145         and $0xffffbfff, %ecx
    146         push %ecx
     162        andl $0xffffbfff, (%esp)
    147163        popfl
    148 .endm   
     164.endm
    149165
    150166/*
     
    160176sysenter_handler:
    161177        sti
    162         pushl %ebp      # remember user stack
    163         pushl %edi      # remember return user address
    164 
    165         pushl %gs       # remember TLS
    166 
    167         pushl %eax      # syscall number
    168         subl $8, %esp   # unused sixth and fifth argument
    169         pushl %esi      # fourth argument
    170         pushl %ebx      # third argument
    171         pushl %ecx      # second argument
    172         pushl %edx      # first argument
    173 
     178        pushl %ebp  /* remember user stack */
     179        pushl %edi  /* remember return user address */
     180       
     181        xorl %ebp, %ebp  /* stop stack traces here */
     182       
     183        pushl %gs  /* remember TLS */
     184       
     185        pushl %eax     /* syscall number */
     186        subl $8, %esp  /* unused sixth and fifth argument */
     187        pushl %esi     /* fourth argument */
     188        pushl %ebx     /* third argument */
     189        pushl %ecx     /* second argument */
     190        pushl %edx     /* first argument */
     191       
    174192        movw $16, %ax
    175193        movw %ax, %ds
    176194        movw %ax, %es
    177 
     195       
    178196        cld
    179197        call syscall_handler
    180         addl $28, %esp  # remove arguments from stack
    181 
    182         pop %gs         # restore TLS
    183 
    184         pop %edx        # prepare return EIP for SYSEXIT
    185         pop %ecx        # prepare userspace ESP for SYSEXIT
    186 
    187         sysexit         # return to userspace
    188 
    189 
    190 ## Declare interrupt handlers
    191 #
    192 # Declare interrupt handlers for n interrupt
    193 # vectors starting at vector i.
    194 #
    195 # The handlers setup data segment registers
    196 # and call exc_dispatch().
    197 #
    198 #define INTERRUPT_ALIGN 64
     198        addl $28, %esp  /* remove arguments from stack */
     199       
     200        pop %gs  /* restore TLS */
     201       
     202        pop %edx  /* prepare return EIP for SYSEXIT */
     203        pop %ecx  /* prepare userspace ESP for SYSEXIT */
     204       
     205        sysexit   /* return to userspace */
     206
     207#define ISTATE_OFFSET_EAX         0
     208#define ISTATE_OFFSET_EBX         4
     209#define ISTATE_OFFSET_ECX         8
     210#define ISTATE_OFFSET_EDX         12
     211#define ISTATE_OFFSET_EDI         16
     212#define ISTATE_OFFSET_ESI         20
     213#define ISTATE_OFFSET_EBP         24
     214#define ISTATE_OFFSET_EBP_FRAME   28
     215#define ISTATE_OFFSET_EIP_FRAME   32
     216#define ISTATE_OFFSET_GS          36
     217#define ISTATE_OFFSET_FS          40
     218#define ISTATE_OFFSET_ES          44
     219#define ISTATE_OFFSET_DS          48
     220#define ISTATE_OFFSET_ERROR_WORD  52
     221#define ISTATE_OFFSET_EIP         56
     222#define ISTATE_OFFSET_CS          60
     223#define ISTATE_OFFSET_EFLAGS      64
     224#define ISTATE_OFFSET_ESP         68
     225#define ISTATE_OFFSET_SS          72
     226
     227/*
     228 * Size of the istate structure without the hardware-saved part
     229 * and without the error word.
     230 */
     231#define ISTATE_SOFT_SIZE  52
     232
     233/** Declare interrupt handlers
     234 *
     235 * Declare interrupt handlers for n interrupt
     236 * vectors starting at vector i.
     237 *
     238 * The handlers setup data segment registers
     239 * and call exc_dispatch().
     240 *
     241 */
     242#define INTERRUPT_ALIGN  256
     243
    199244.macro handler i n
    200        
    201         .ifeq \i - 0x30     # Syscall handler
     245        .ifeq \i - 0x30
     246                /* Syscall handler */
    202247                pushl %ds
    203248                pushl %es
     
    205250                pushl %gs
    206251               
    207                 #
    208                 # Push syscall arguments onto the stack
    209                 #
    210                 # NOTE: The idea behind the order of arguments passed in registers is to
    211                 #       use all scratch registers first and preserved registers next.
    212                 #       An optimized libc syscall wrapper can make use of this setup.
    213                 #
     252                /*
     253                 * Push syscall arguments onto the stack
     254                 *
     255                 * NOTE: The idea behind the order of arguments passed
     256                 *       in registers is to use all scratch registers
     257                 *       first and preserved registers next. An optimized
     258                 *       libc syscall wrapper can make use of this setup.
     259                 *
     260                 */
    214261                pushl %eax
    215262                pushl %ebp
     
    220267                pushl %edx
    221268               
    222                 # we must fill the data segment registers
     269                /* We must fill the data segment registers */
    223270                movw $16, %ax
    224271                movw %ax, %ds
    225272                movw %ax, %es
    226273               
     274                xorl %ebp, %ebp
     275               
    227276                cld
    228277                sti
    229                 # syscall_handler(edx, ecx, ebx, esi, edi, ebp, eax)
     278               
     279                /* Call syscall_handler(edx, ecx, ebx, esi, edi, ebp, eax) */
    230280                call syscall_handler
    231281                cli
    232                 addl $28, %esp         # clean-up of parameters
     282               
     283                movl 20(%esp), %ebp  /* restore EBP */
     284                addl $28, %esp       /* clean-up of parameters */
    233285               
    234286                popl %gs
     
    241293        .else
    242294                /*
    243                  * This macro distinguishes between two versions of ia32 exceptions.
    244                  * One version has error word and the other does not have it.
    245                  * The latter version fakes the error word on the stack so that the
    246                  * handlers and istate_t can be the same for both types.
     295                 * This macro distinguishes between two versions of ia32
     296                 * exceptions. One version has error word and the other
     297                 * does not have it. The latter version fakes the error
     298                 * word on the stack so that the handlers and istate_t
     299                 * can be the same for both types.
    247300                 */
    248301                .iflt \i - 32
    249302                        .if (1 << \i) & ERROR_WORD_INTERRUPT_LIST
    250303                                /*
    251                                  * With error word, do nothing
     304                                 * Exception with error word: do nothing
    252305                                 */
    253306                        .else
    254307                                /*
    255                                  * Version without error word
     308                                 * Exception without error word: fake up one
    256309                                 */
    257                                 subl $4, %esp
     310                                pushl $0
    258311                        .endif
    259312                .else
    260313                        /*
    261                          * Version without error word
     314                         * Interrupt: fake up one
    262315                         */
    263                         subl $4, %esp
     316                        pushl $0
    264317                .endif
    265318               
    266                 pushl %ds
    267                 pushl %es
    268                 pushl %fs
    269                 pushl %gs
    270                
    271                 pushl %ebp
    272                 pushl %edx
    273                 pushl %ecx
    274                 pushl %eax
    275                
    276                 # we must fill the data segment registers
    277                
    278                 movw $16, %ax
    279                 movw %ax, %ds
    280                 movw %ax, %es
    281                
    282                 # stop stack traces here
     319                subl $ISTATE_SOFT_SIZE, %esp
     320               
     321                /*
     322                 * Save the general purpose registers.
     323                 */
     324                movl %eax, ISTATE_OFFSET_EAX(%esp)
     325                movl %ebx, ISTATE_OFFSET_EBX(%esp)
     326                movl %ecx, ISTATE_OFFSET_ECX(%esp)
     327                movl %edx, ISTATE_OFFSET_EDX(%esp)
     328                movl %edi, ISTATE_OFFSET_EDI(%esp)
     329                movl %esi, ISTATE_OFFSET_ESI(%esp)
     330                movl %ebp, ISTATE_OFFSET_EBP(%esp)
     331               
     332                /*
     333                 * Save the selector registers.
     334                 */
     335                movl %gs, %eax
     336                movl %fs, %ebx
     337                movl %es, %ecx
     338                movl %ds, %edx
     339               
     340                movl %eax, ISTATE_OFFSET_GS(%esp)
     341                movl %ebx, ISTATE_OFFSET_FS(%esp)
     342                movl %ecx, ISTATE_OFFSET_ES(%esp)
     343                movl %edx, ISTATE_OFFSET_DS(%esp)
     344               
     345                /*
     346                 * Switch to kernel selectors.
     347                 */
     348                movl $16, %eax
     349                movl %eax, %ds
     350                movl %eax, %es
     351               
     352                /*
     353                 * Imitate a regular stack frame linkage.
     354                 * Stop stack traces here if we came from userspace.
     355                 */
     356                cmpl $8, ISTATE_OFFSET_CS(%esp)
     357                jz 0f
    283358                xorl %ebp, %ebp
    284359               
    285                 pushl %esp          # *istate
    286                 pushl $(\i)         # intnum
    287                 call exc_dispatch   # exc_dispatch(intnum, *istate)
    288                 addl $8, %esp       # Clear arguments from stack
    289                
    290                 CLEAR_NT_FLAG # Modifies %ecx
    291                
    292                 popl %eax
    293                 popl %ecx
    294                 popl %edx
    295                 popl %ebp
    296                
    297                 popl %gs
    298                 popl %fs
    299                 popl %es
    300                 popl %ds
    301                
    302                 # skip error word, no matter whether real or fake
    303                 addl $4, %esp
    304                 iret
     360                0:
     361               
     362                        movl %ebp, ISTATE_OFFSET_EBP_FRAME(%esp)
     363                        movl ISTATE_OFFSET_EIP(%esp), %eax
     364                        movl %eax, ISTATE_OFFSET_EIP_FRAME(%esp)
     365                        leal ISTATE_OFFSET_EBP_FRAME(%esp), %ebp
     366                       
     367                        cld
     368                       
     369                        pushl %esp   /* pass istate address */
     370                        pushl $(\i)  /* pass intnum */
     371                       
     372                        /* Call exc_dispatch(intnum, istate) */
     373                        call exc_dispatch
     374                       
     375                        addl $8, %esp  /* clear arguments from the stack */
     376                       
     377                        CLEAR_NT_FLAG
     378                       
     379                        /*
     380                         * Restore the selector registers.
     381                         */
     382                        movl ISTATE_OFFSET_GS(%esp), %eax
     383                        movl ISTATE_OFFSET_FS(%esp), %ebx
     384                        movl ISTATE_OFFSET_ES(%esp), %ecx
     385                        movl ISTATE_OFFSET_DS(%esp), %edx
     386                       
     387                        movl %eax, %gs
     388                        movl %ebx, %fs
     389                        movl %ecx, %es
     390                        movl %edx, %ds
     391                       
     392                        /*
     393                         * Restore the scratch registers and the preserved
     394                         * registers the handler cloberred itself
     395                         * (i.e. EBX and EBP).
     396                         */
     397                        movl ISTATE_OFFSET_EAX(%esp), %eax
     398                        movl ISTATE_OFFSET_EBX(%esp), %ebx
     399                        movl ISTATE_OFFSET_ECX(%esp), %ecx
     400                        movl ISTATE_OFFSET_EDX(%esp), %edx
     401                        movl ISTATE_OFFSET_EBP(%esp), %ebp
     402                       
     403                        addl $(ISTATE_SOFT_SIZE + 4), %esp
     404                        iret
     405               
    305406        .endif
    306407       
    307408        .align INTERRUPT_ALIGN
    308         .if (\n- \i) - 1
     409        .if (\n - \i) - 1
    309410                handler "(\i + 1)", \n
    310411        .endif
    311412.endm
    312413
    313 # keep in sync with pm.h !!!
    314 IDT_ITEMS = 64
     414/* Keep in sync with pm.h! */
     415#define IDT_ITEMS  64
     416
    315417.align INTERRUPT_ALIGN
    316418interrupt_handlers:
    317 h_start:
    318         handler 0 IDT_ITEMS
    319 h_end:
     419        h_start:
     420                handler 0 IDT_ITEMS
     421        h_end:
     422
     423/** Print Unicode character to EGA display.
     424 *
     425 * If CONFIG_EGA is undefined or CONFIG_FB is defined
     426 * then this function does nothing.
     427 *
     428 * Since the EGA can only display Extended ASCII (usually
     429 * ISO Latin 1) characters, some of the Unicode characters
     430 * can be displayed in a wrong way. Only the newline character
     431 * is interpreted, all other characters (even unprintable) are
     432 * printed verbatim.
     433 *
     434 * @param %ebp+0x08 Unicode character to be printed.
     435 *
     436 */
     437early_putchar:
     438       
     439#if ((defined(CONFIG_EGA)) && (!defined(CONFIG_FB)))
     440       
     441        /* Prologue, save preserved registers */
     442        pushl %ebp
     443        movl %esp, %ebp
     444        pushl %ebx
     445        pushl %esi
     446        pushl %edi
     447       
     448        movl $(PA2KA(0xb8000)), %edi  /* base of EGA text mode memory */
     449        xorl %eax, %eax
     450       
     451        /* Read bits 8 - 15 of the cursor address */
     452        movw $0x3d4, %dx
     453        movb $0xe, %al
     454        outb %al, %dx
     455       
     456        movw $0x3d5, %dx
     457        inb %dx, %al
     458        shl $8, %ax
     459       
     460        /* Read bits 0 - 7 of the cursor address */
     461        movw $0x3d4, %dx
     462        movb $0xf, %al
     463        outb %al, %dx
     464       
     465        movw $0x3d5, %dx
     466        inb %dx, %al
     467       
     468        /* Sanity check for the cursor on screen */
     469        cmp $2000, %ax
     470        jb early_putchar_cursor_ok
     471       
     472                movw $1998, %ax
     473       
     474        early_putchar_cursor_ok:
     475       
     476        movw %ax, %bx
     477        shl $1, %eax
     478        addl %eax, %edi
     479       
     480        movl 0x08(%ebp), %eax
     481       
     482        cmp $0x0a, %al
     483        jne early_putchar_print
     484       
     485                /* Interpret newline */
     486               
     487                movw %bx, %ax  /* %bx -> %dx:%ax */
     488                xorw %dx, %dx
     489               
     490                movw $80, %cx
     491                idivw %cx, %ax  /* %dx = %bx % 80 */
     492               
     493                /* %bx <- %bx + 80 - (%bx % 80) */
     494                addw %cx, %bx
     495                subw %dx, %bx
     496               
     497                jmp early_putchar_newline
     498       
     499        early_putchar_print:
     500       
     501                /* Print character */
     502               
     503                movb $0x0e, %ah  /* black background, yellow foreground */
     504                stosw
     505                inc %bx
     506       
     507        early_putchar_newline:
     508       
     509        /* Sanity check for the cursor on the last line */
     510        cmp $2000, %bx
     511        jb early_putchar_no_scroll
     512       
     513                /* Scroll the screen (24 rows) */
     514                movl $(PA2KA(0xb80a0)), %esi
     515                movl $(PA2KA(0xb8000)), %edi
     516                movl $1920, %ecx
     517                rep movsw
     518               
     519                /* Clear the 24th row */
     520                xorl %eax, %eax
     521                movl $80, %ecx
     522                rep stosw
     523               
     524                /* Go to row 24 */
     525                movw $1920, %bx
     526       
     527        early_putchar_no_scroll:
     528       
     529        /* Write bits 8 - 15 of the cursor address */
     530        movw $0x3d4, %dx
     531        movb $0xe, %al
     532        outb %al, %dx
     533       
     534        movw $0x3d5, %dx
     535        movb %bh, %al
     536        outb %al, %dx
     537       
     538        /* Write bits 0 - 7 of the cursor address */
     539        movw $0x3d4, %dx
     540        movb $0xf, %al
     541        outb %al, %dx
     542       
     543        movw $0x3d5, %dx
     544        movb %bl, %al
     545        outb %al, %dx
     546       
     547        /* Epilogue, restore preserved registers */
     548        popl %edi
     549        popl %esi
     550        popl %ebx
     551        leave
     552       
     553#endif
     554       
     555        ret
    320556
    321557.data
Note: See TracChangeset for help on using the changeset viewer.