"Fossies" - the Fresh Open Source Software Archive

Member "grub-2.00/grub-core/boot/mips/loongson/fwstart.S" (26 Jun 2012, 27759 Bytes) of archive /linux/misc/grub-2.00.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) PowerPC Assembler source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file.

    1 /*
    2  *  GRUB  --  GRand Unified Bootloader
    3  *  Copyright (C) 2000,2001,2002,2003,2004,2005,2007,2008,2009,2010  Free Software Foundation, Inc.
    4  *
    5  *  GRUB is free software: you can redistribute it and/or modify
    6  *  it under the terms of the GNU General Public License as published by
    7  *  the Free Software Foundation, either version 3 of the License, or
    8  *  (at your option) any later version.
    9  *
   10  *  GRUB is distributed in the hope that it will be useful,
   11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   13  *  GNU General Public License for more details.
   14  *
   15  *  You should have received a copy of the GNU General Public License
   16  *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
   17  */
   18 
   19 #include <grub/mips/loongson/serial.h>
   20 #include <grub/mips/loongson/pci.h>
   21 #include <grub/mips/loongson.h>
   22 #include <grub/pci.h>
   23 #include <grub/machine/serial.h>
   24 #include <grub/machine/kernel.h>
   25 #include <grub/ns8250.h>
   26 #include <grub/cs5536.h>
   27 #include <grub/smbus.h>
   28 
   29 #ifndef FULOONG2F
   30 #include <grub/vgaregs.h>
   31 #define GRUB_SM712_REG_BASE 0x700000
   32 #define GRUB_SM712_PCIID 0x0712126f
   33 #endif
   34 
   35 #ifdef FULOONG2F
   36 #define GRUB_MACHINE_SERIAL_PORT GRUB_MACHINE_SERIAL_PORT2
   37 #define GRUB_MACHINE_SERIAL_DIVISOR_115200 GRUB_MACHINE_SERIAL_PORT2_DIVISOR_115200
   38 #else
   39 #define GRUB_MACHINE_SERIAL_PORT GRUB_MACHINE_SERIAL_PORT0
   40 #define GRUB_MACHINE_SERIAL_DIVISOR_115200 GRUB_MACHINE_SERIAL_PORT0_DIVISOR_115200
   41 #endif
   42 
   43     .set noreorder
   44     .set noat
   45     .set nomacro
   46     .set mips3
   47 
   48     .global start,_start,__start
   49 start:
   50 _start:
   51 __start:    
   52     /* Put serial init as soon as possible.  But on Fuloong2f serial is past
   53        Geode, so on Fuloong2f we need Geode first.
   54     */
   55 #ifndef FULOONG2F
   56     bal serial_hw_init
   57      nop
   58 #endif
   59 
   60     /* Find CS5536 controller.  */
   61     /* $t4 chooses device in priority encoding.  */
   62     /* Resulting value is kept in GRUB_MACHINE_PCI_CONF_CTRL_REG.
   63        This way we don't need to sacrifice a register for it.  */
   64 retry_cs5536:   
   65     /* We have only one bus (0). Function is 0.  */
   66     lui $t0, %hi(GRUB_MACHINE_PCI_CONF_CTRL_REG_ADDR)
   67     lui $t1, %hi(GRUB_MACHINE_PCI_CONFSPACE)
   68     lui $t3, %hi(GRUB_CS5536_PCIID)
   69     addiu $t3, $t3, %lo(GRUB_CS5536_PCIID)
   70     ori $t4, $zero, 1
   71 1:
   72     andi $t4, $t4, ((1 << GRUB_PCI_NUM_DEVICES) - 1)
   73     /* In case of failure try again. CS5536 may be slow to come up.  */
   74     beql  $t4, $zero, retry_cs5536
   75      nop
   76     sw   $t4, %lo(GRUB_MACHINE_PCI_CONF_CTRL_REG_ADDR) ($t0)
   77     lw   $t2, (%lo(GRUB_MACHINE_PCI_CONFSPACE) + GRUB_PCI_REG_PCI_ID) ($t1)
   78     bnel  $t2, $t3, 1b
   79      sll $t4, $t4, 1
   80 
   81 #ifndef FULOONG2F
   82     lui $a0, %hi(cs5536_found)
   83     bal message
   84      addiu $a0, $a0, %lo(cs5536_found)
   85     bal printhex
   86      move $a0, $t4
   87 #endif
   88 
   89     lui $t0, %hi(GRUB_MACHINE_PCI_CONFSPACE)
   90     li  $t1, GRUB_CS5536_MSR_MAILBOX_CONFIG_ENABLED
   91     sw  $t1, (%lo(GRUB_MACHINE_PCI_CONFSPACE) + GRUB_CS5536_MSR_MAILBOX_CONFIG) ($t0)
   92     
   93     /* Set GPIO LBAR.  */
   94     lui $a0, %hi(GRUB_CS5536_MSR_GPIO_BAR)
   95     addiu $a0, $a0, %lo(GRUB_CS5536_MSR_GPIO_BAR)
   96     ori $a1, $zero, GRUB_CS5536_LBAR_GPIO
   97     /* Set mask to 0xf and enabled bit to 1.  */
   98     bal wrmsr
   99      ori $a2, $zero, ((GRUB_CS5536_LBAR_MASK_MASK \
  100                       | GRUB_CS5536_LBAR_ENABLE) >> 32)
  101 
  102     bal gpio_init
  103      nop
  104 
  105 #ifdef FULOONG2F
  106     bal serial_hw_init
  107      nop
  108 #endif
  109 
  110     /* Initialise SMBus controller.  */
  111     /* Set SMBUS LBAR.  */
  112     lui $a0, %hi(GRUB_CS5536_MSR_SMB_BAR)
  113     addiu $a0, $a0, %lo(GRUB_CS5536_MSR_SMB_BAR)
  114     ori $a1, $zero, GRUB_CS5536_LBAR_SMBUS
  115     /* Set mask to 0xf and enabled bit to 1.  */
  116     bal wrmsr
  117      ori $a2, $zero, ((GRUB_CS5536_LBAR_MASK_MASK \
  118                        | GRUB_CS5536_LBAR_ENABLE) >> 32)
  119 
  120     lui $a0, %hi(smbus_enabled)
  121     bal message
  122       addiu $a0, $a0, %lo(smbus_enabled)
  123 
  124     lui $t0, %hi(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_SMBUS)
  125 
  126     /* Disable SMB.  */
  127     sb $zero, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL2) ($t0)
  128 
  129     /* Disable interrupts.  */
  130     sb $zero, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1) ($t0)
  131 
  132     /* Set as master.  */
  133     sb $zero, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_ADDR) ($t0)
  134 
  135     /* Launch SMBus controller at slowest speed possible.  */
  136     ori $t1, $zero, 0xff
  137     sb $t1, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL3) ($t0)
  138     sb $t1, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL2) ($t0)
  139 
  140     /* Yeeloong and Fuloong2f have only one memory slot.  */
  141     /* Output first byte on serial for debugging.  */
  142     ori $a1, $zero, GRUB_SMB_RAM_START_ADDR
  143     bal read_spd
  144      move $a0, $zero
  145     bal printhex
  146      move $a0, $v0
  147 
  148     bal read_spd
  149      ori $a0, $zero, GRUB_SMBUS_SPD_MEMORY_TYPE_ADDR
  150     ori $t0, $zero, GRUB_SMBUS_SPD_MEMORY_TYPE_DDR2
  151     lui $a0, %hi(unimplemented_memory_type)
  152     bne $t0, $v0, fatal
  153      addiu $a0, $a0, %lo(unimplemented_memory_type)
  154 
  155     /* And here is our goal: DDR2 controller initialisation.  */
  156         lui $t0, %hi(GRUB_CPU_LOONGSON_CORECFG)
  157         ld  $t1, %lo(GRUB_CPU_LOONGSON_CORECFG) ($t0)
  158     /* Use addiu for sign-extension.  */
  159     addiu   $t2, $zero, ~(GRUB_CPU_LOONGSON_CORECFG_DISABLE_DDR2_SPACE|GRUB_CPU_LOONGSON_CORECFG_BUFFER_CPU)
  160     and $t1, $t1, $t2
  161     sd  $t1, %lo (GRUB_CPU_LOONGSON_CORECFG) ($t0)
  162 
  163     b continue
  164 
  165     . = start + GRUB_CPU_LOONGSON_FLASH_TLB_REFILL - GRUB_CPU_LOONGSON_FLASH_START
  166 tlb_refill: 
  167     mfc0 $s1, GRUB_CPU_LOONGSON_COP0_EPC
  168     mfc0 $s2, GRUB_CPU_LOONGSON_COP0_BADVADDR
  169     move $s3, $ra
  170     lui $a0, %hi(epc)
  171     bal message
  172      addiu $a0, $a0, %lo(epc)
  173 
  174     bal printhex
  175      move $a0, $s1
  176 
  177     lui $a0, %hi(badvaddr)
  178     bal message
  179      addiu $a0, $a0, %lo(badvaddr)
  180 
  181     bal printhex
  182      move $a0, $s2
  183 
  184     lui $a0, %hi(return_msg)
  185     bal message
  186      addiu $a0, $a0, %lo(return_msg)
  187 
  188     bal printhex
  189      move $a0, $s3
  190     
  191     lui $a0, %hi(newline)
  192     bal message
  193      addiu $a0, $a0, %lo(newline)
  194 
  195     lui $a0, %hi(unhandled_tlb_refill)
  196     b fatal
  197      addiu $a0, $a0, %lo(unhandled_tlb_refill)
  198 
  199     . = start + GRUB_CPU_LOONGSON_FLASH_CACHE_ERROR - GRUB_CPU_LOONGSON_FLASH_START
  200 cache_error:
  201     lui $a0, %hi(unhandled_cache_error)
  202     b fatal
  203      addiu $a0, $a0, %lo(unhandled_cache_error)
  204 
  205     . = start + GRUB_CPU_LOONGSON_FLASH_OTHER_EXCEPTION - GRUB_CPU_LOONGSON_FLASH_START
  206 other_exception:
  207     mfc0 $s0, GRUB_CPU_LOONGSON_COP0_CAUSE
  208     mfc0 $s1, GRUB_CPU_LOONGSON_COP0_EPC
  209     mfc0 $s2, GRUB_CPU_LOONGSON_COP0_BADVADDR
  210     lui $a0, %hi(cause)
  211     bal message
  212      addiu $a0, $a0, %lo(cause)
  213 
  214     bal printhex
  215      move $a0, $s0
  216 
  217     lui $a0, %hi(epc)
  218     bal message
  219      addiu $a0, $a0, %lo(epc)
  220 
  221     bal printhex
  222      move $a0, $s1
  223 
  224     lui $a0, %hi(badvaddr)
  225     bal message
  226      addiu $a0, $a0, %lo(badvaddr)
  227 
  228     bal printhex
  229      move $a0, $s2
  230     
  231     lui $a0, %hi(newline)
  232     bal message
  233      addiu $a0, $a0, %lo(newline)
  234     
  235     lui $a0, %hi(unhandled_exception)
  236     b fatal
  237      addiu $a0, $a0, %lo(unhandled_exception)
  238 
  239 gpio_init:
  240     lui $t0, %hi(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_GPIO)
  241     addiu  $t0, $t0, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_GPIO)
  242     lui $t1, %hi (gpio_dump)
  243     addiu $t1, $t1, %lo (gpio_dump)
  244 
  245 1:  
  246     lw $t2, 0($t1)
  247     sw $t2, 0($t0)
  248     addiu $t0, $t0, 4
  249     addiu $t1, $t1, 4
  250     lui $t2, %hi (gpio_dump_end)
  251     addiu $t2, $t2, %lo (gpio_dump_end)
  252     bne $t1, $t2, 1b
  253      nop
  254     jr $ra
  255      nop
  256 
  257     /* Same as similarly named C function but in asm since
  258        we need it early.  */
  259     /* In: none. Out: none. Clobbered: $t0, $t1, $t2, $a0, $a1, $a2.  */
  260 serial_hw_init:
  261     move $t2, $ra
  262 #ifdef FULOONG2F
  263     lui $a0, %hi(GRUB_CS5536_MSR_DIVIL_LEG_IO)
  264     addiu $a0, $a0, %lo(GRUB_CS5536_MSR_DIVIL_LEG_IO)
  265     lui $a1, %hi (GRUB_CS5536_MSR_DIVIL_LEG_IO_UART2_COM3    \
  266              | GRUB_CS5536_MSR_DIVIL_LEG_IO_F_REMAP     \
  267              | GRUB_CS5536_MSR_DIVIL_LEG_IO_MODE_X86    \
  268                  | GRUB_CS5536_MSR_DIVIL_LEG_IO_UART1_COM1)
  269     ori $a1, $a1, (GRUB_CS5536_MSR_DIVIL_LEG_IO_RTC_ENABLE0 \
  270                | GRUB_CS5536_MSR_DIVIL_LEG_IO_RTC_ENABLE1)
  271     bal wrmsr
  272      move $a2, $zero
  273 
  274     lui $a0, %hi(GRUB_CS5536_MSR_DIVIL_UART1_CONF)
  275     addiu $a0, $a0, %lo(GRUB_CS5536_MSR_DIVIL_UART1_CONF)
  276     li $a1, 2
  277     bal wrmsr
  278      move $a2, $zero
  279 
  280     lui $a0, %hi(GRUB_CS5536_MSR_DIVIL_UART2_CONF)
  281     addiu $a0, $a0, %lo(GRUB_CS5536_MSR_DIVIL_UART2_CONF)
  282     li $a1, 2
  283     bal wrmsr
  284      move $a2, $zero
  285 #endif
  286     
  287     lui $t0, %hi (GRUB_MACHINE_SERIAL_PORT)
  288 
  289     /* Turn off the interrupt.  */
  290     sb $zero, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_IER)($t0)
  291 
  292     /* Set DLAB.  */
  293     ori $t1, $zero, UART_DLAB
  294     sb  $t1, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_LCR)($t0)
  295 
  296     /* Set the baud rate 115200.  */
  297     ori $t1, $zero, GRUB_MACHINE_SERIAL_DIVISOR_115200
  298     sb $t1, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_DLL)($t0) 
  299     sb $zero, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_DLH)($t0) 
  300 
  301     /* Set the line status.  */
  302     ori $t1, $zero, (UART_NO_PARITY | UART_8BITS_WORD | UART_1_STOP_BIT)
  303         sb  $t1, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_LCR)($t0)
  304 
  305     /* Enable the FIFO.  */
  306     ori $t1, $zero, UART_ENABLE_FIFO_TRIGGER1
  307     sb $t1, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_FCR)($t0)
  308 
  309     /* Turn on DTR and RTS.  */
  310     ori $t1, $zero, UART_ENABLE_DTRRTS
  311     sb  $t1, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_MCR)($t0)
  312 
  313     /* Let message return to original caller.  */
  314     lui  $a0, %hi(notification_string)
  315     addiu $a0, $a0, %lo(notification_string)
  316     move $ra, $t2
  317 
  318     /* Print message on serial console.  */
  319     /* In: $a0 = asciiz message. Out: none. Clobbered: $t0, $t1, $a0.  */
  320 message:
  321     lui $t0, %hi (GRUB_MACHINE_SERIAL_PORT)
  322 1:
  323     lb $t1, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_LSR)($t0)
  324     andi $t1, $t1, UART_EMPTY_TRANSMITTER
  325     beq $t1, $zero, 1b
  326      nop
  327     lb  $t1, 0($a0)
  328     sb  $t1, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_TX)($t0)
  329     bne $t1, $zero, 1b
  330      addiu $a0, $a0, 1
  331     jr  $ra
  332      nop
  333     
  334     /* Print 32-bit hexadecimal on serial.
  335            In:  $a0. Out: None. Clobbered: $a0, $t0, $t1, $t2
  336     */
  337 printhex:
  338     lui $t0, %hi  (GRUB_MACHINE_SERIAL_PORT)
  339     ori $t2, $zero, 8
  340 1:
  341     lb $t1, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_LSR)($t0)
  342     andi $t1, $t1, UART_EMPTY_TRANSMITTER
  343     beq $t1, $zero, 1b
  344      nop
  345     srl  $t1, $a0, 28
  346     addiu $t1, $t1, -10
  347     blt  $t1, $zero, 2f
  348      sll  $a0, $a0, 4
  349     addiu $t1, $t1, 'A'-10-'0' 
  350 2:  addiu $t1, $t1, '0'+10
  351     sb  $t1, (%lo (GRUB_MACHINE_SERIAL_PORT) + UART_TX)($t0)
  352     addiu $t2, $t2, -1
  353     bne $t2, $zero, 1b
  354      nop
  355     jr  $ra
  356      nop
  357 
  358 fatal:
  359     bal message
  360      nop
  361 self:
  362     b self
  363      nop
  364     
  365     /* Write CS5536 MSR.
  366            In:   $a0 address, $a1 lower word, $a2 upper word.
  367            Out:  None
  368            Clobbered:    $t0
  369     */
  370 wrmsr:
  371     lui $t0, %hi(GRUB_MACHINE_PCI_CONFSPACE)
  372     sw  $a0, (%lo(GRUB_MACHINE_PCI_CONFSPACE) + GRUB_CS5536_MSR_MAILBOX_ADDR) ($t0)
  373     sw  $a1, (%lo(GRUB_MACHINE_PCI_CONFSPACE) + GRUB_CS5536_MSR_MAILBOX_DATA0) ($t0)
  374     jr $ra
  375      sw  $a2, (%lo(GRUB_MACHINE_PCI_CONFSPACE) + GRUB_CS5536_MSR_MAILBOX_DATA1) ($t0)
  376 
  377     /* Wait for SMBus data or empty transmitter.  */
  378     /* In: $a0 = exception handler. Out: none. Clobbered: $t0, $t1  */
  379 smbus_wait:
  380 1:  
  381     lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_STATUS + GRUB_MACHINE_PCI_IO_BASE)
  382     lb $t0, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_STATUS + GRUB_MACHINE_PCI_IO_BASE) ($t0)
  383     andi $t1, $t0, GRUB_CS5536_SMB_REG_STATUS_SDAST
  384     bne $t1, $zero, return
  385      nop
  386     andi $t1, $t0, (GRUB_CS5536_SMB_REG_STATUS_BER | GRUB_CS5536_SMB_REG_STATUS_NACK)
  387     beq $t1, $zero, 1b
  388      nop
  389     jr $a0
  390      nop
  391 return:
  392     jr $ra
  393      nop
  394     
  395     /* Read SPD byte. In: $a0 byte, $a1 device. Out: $v0 read byte (0x100 on failure).
  396            Clobbered: $t0, $t1, $t2, $t3, $a0. */
  397 read_spd:
  398     move $t2, $a0
  399     move $t3, $ra
  400     lui $a0, %hi(read_spd_fail)
  401     addiu $a0, $a0, %hi(read_spd_fail)
  402 
  403     /* Send START.  */
  404     lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE)
  405     lb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) ($t0)
  406     ori $t1, $t1, GRUB_CS5536_SMB_REG_CTRL1_START
  407     bal smbus_wait
  408      sb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) ($t0)
  409     
  410     /* Send device address.  */
  411     lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE)
  412     sll $t1, $a1, 1
  413     bal smbus_wait
  414      sb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE) ($t0)
  415 
  416     /* Send ACK.  */
  417     lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE)
  418     lb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) ($t0)
  419     ori $t1, $t1, GRUB_CS5536_SMB_REG_CTRL1_ACK
  420     sb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) ($t0)
  421 
  422     /* Send byte address.  */
  423     lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE)
  424     bal smbus_wait
  425      sb $t2, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE) ($t0)
  426 
  427     /* Send START.  */
  428     lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE)
  429     lb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) ($t0)
  430     ori $t1, $t1, GRUB_CS5536_SMB_REG_CTRL1_START
  431     bal smbus_wait
  432      sb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) ($t0)
  433 
  434     /* Send device address.  */
  435     lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE)
  436     sll $t1, $a1, 1
  437     ori $t1, $t1, 1
  438     bal smbus_wait
  439      sb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE) ($t0)
  440 
  441     /* Send STOP.  */
  442     lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE)
  443     lb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) ($t0)
  444     ori $t1, $t1, GRUB_CS5536_SMB_REG_CTRL1_STOP
  445     bal smbus_wait
  446      sb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) ($t0)
  447 
  448     lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE)
  449     lb $v0, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE) ($t0)
  450     jr $t3
  451      andi $v0, $v0, 0xff
  452 read_spd_fail:
  453     jr $t3
  454      ori $v0, $v0, 0x100
  455 
  456 notification_string:    .asciz "GRUB "
  457 cs5536_found:   .asciz "CS5536 at "
  458 sm_failed: .asciz "SM transaction failed.\n\r"
  459 unhandled_tlb_refill:   .asciz "Unhandled TLB refill.\n\r"
  460 unhandled_cache_error:  .asciz "Unhandled cache error.\n\r"
  461 unhandled_exception:    .asciz "Unhandled exception.\n\r"
  462 smbus_enabled:  .asciz "SMBus controller enabled.\n\r"
  463 unimplemented_memory_type:  .asciz "non-DDR2 memory isn't supported.\n\r"
  464 no_cas_latency:     .asciz "Couldn't determine CAS latency.\n\r"
  465 cause:   .asciz "Cause: "
  466 epc:    .asciz "\n\rEPC: "
  467 badvaddr:   .asciz "\n\rBadVaddr: "
  468 newline:    .asciz "\n\r"
  469 return_msg:   .asciz "\n\rReturn address: "
  470 caches_enabled: .asciz "Caches enabled\n\r"
  471 
  472     .p2align 3
  473 
  474 regdump:
  475     .quad 0x0100010000000101 /* 0 */
  476     .quad 0x0100010100000000 /* 2 */
  477     .quad 0x0101000001000000 /* 3 */
  478     .quad 0x0100020200010101 /* 4 */
  479     .quad 0x0a04030603050203 /* 6 */
  480     .quad 0x0f0e040000010a0b /* 7 */
  481 #ifdef FULOONG2F
  482     .quad 0x0000000100000001 /* 8 */
  483 #else
  484     .quad 0x0000010200000102 /* 8 */
  485 #endif
  486     .quad 0x0000060c00000000 /* 9 */
  487     .quad 0x2323233f3f1f0200 /* a */
  488     .quad 0x5f7f232323232323 /* b */
  489     .quad 0x002a3c0615000000 /* c */
  490     .quad 0x002a002a002a002a /* d */
  491     .quad 0x002a002a002a002a /* e */
  492 #ifdef FULOONG2F
  493     .quad 0x00b40020005b0004 /* f */
  494 #else
  495     .quad 0x00b40020006d0004 /* f */
  496 #endif
  497     .quad 0x070007ff00000087 /* 10 */
  498     .quad 0x000000000016101f /* 11 */
  499     .quad 0x001c000000000000 /* 12 */
  500     .quad 0x28e1000200c8006b /* 13 */
  501     .quad 0x0000204200c8002f /* 14 */
  502     .quad 0x0000000000030d40 /* 15 */
  503     .quad 0 /* 16 */
  504     .quad 0 /* 17 */
  505     .quad 0 /* 18 */
  506     .quad 0 /* 19 */
  507     .quad 0 /* 1a */
  508     .quad 0 /* 1b */
  509     .quad 0 /* 1c */
  510 
  511 /* Dump of GPIO connections. FIXME: Remove useless and macroify.  */
  512 gpio_dump:
  513 #ifdef FULOONG2F
  514     .long 0xffff0000, 0x2eefd110, 0xffff0000, 0xffff0000
  515     .long 0x2eefd110, 0xffff0000, 0x1000efff, 0xefff1000
  516     .long 0x3df3c20c, 0xffff0000, 0xffff0000, 0xffff0000
  517     .long 0x7df3820c, 0x3df3c20c, 0xffff0000, 0x00000000
  518     .long 0xffff0000, 0xffff0000, 0x3de3c21c, 0x3d83c27c
  519     .long 0x00000000, 0x00000000, 0x00000000, 0x00000000
  520     .long 0x00000000, 0x00000000, 0x00000000, 0x00000000
  521     .long 0x00000000, 0x00000000, 0x00000000, 0x00000000
  522     .long 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000
  523     .long 0xffff0000, 0xffff0000, 0x0000ffff, 0xffff0000
  524     .long 0xefff1000, 0xffff0000, 0xffff0000, 0xffff0000
  525     .long 0xefff1000, 0xefff1000, 0xffff0000, 0x00000000
  526     .long 0xffff0000, 0xffff0000, 0xefff1000, 0xefff1000
  527     .long 0x00000000, 0x00000000, 0x00000000, 0x00000000
  528     .long 0x00000000, 0x00000000, 0x00000000, 0x00000000
  529     .long 0x00000000, 0x00000000, 0x00000000, 0x00000000
  530 #else
  531     .long 0xffff0000, 0x2ffdd002, 0xffff0000, 0xffff0000
  532     .long 0x2fffd000, 0xffff0000, 0x1000efff, 0xefff1000
  533     .long 0x3ffbc004, 0xffff0000, 0xffff0000, 0xffff0000
  534     .long 0x3ffbc004, 0x3ffbc004, 0xffff0000, 0x00000000
  535     .long 0xffff0000, 0xffff0000, 0x3ffbc004, 0x3f9bc064
  536     .long 0x00000000, 0x00000000, 0x00000000, 0x00000000
  537     .long 0x00000000, 0x00000000, 0x00000000, 0x00000000
  538     .long 0x00000000, 0x00000000, 0x00000000, 0x00000000
  539     .long 0xffff0000, 0xffff0000, 0xffff0000, 0xffff0000
  540     .long 0xffff0000, 0xffff0000, 0x0000ffff, 0xffff0000
  541     .long 0xefff1000, 0xffff0000, 0xffff0000, 0xffff0000
  542     .long 0xefff1000, 0xefff1000, 0xffff0000, 0x00000000
  543     .long 0xffff0000, 0xffff0000, 0xefff1000, 0xffff0000
  544     .long 0x00000000, 0x00000000, 0x00000000, 0x00000000
  545     .long 0x00000000, 0x00000000, 0x00000000, 0x00000000
  546     .long 0x00000000, 0x50000000, 0x00000000, 0x00000000
  547 #endif
  548 gpio_dump_end:  
  549 
  550     .p2align
  551 
  552 write_dumpreg:  
  553     ld $t2, 0($t6)
  554     sd $t2, 0($t4)
  555     addiu $t4, $t4, GRUB_CPU_LOONGSON_DDR2_REG_STEP
  556     jr $ra
  557      addiu $t6, $t6, GRUB_CPU_LOONGSON_DDR2_REG_SIZE
  558 
  559 continue:
  560     lui $t4, %hi(GRUB_CPU_LOONGSON_DDR2_BASE)
  561     addiu $t4, $t4, %lo(GRUB_CPU_LOONGSON_DDR2_BASE)
  562     lui $t6, %hi(regdump)
  563 
  564     /* 0 */
  565     bal write_dumpreg
  566      addiu $t6, $t6, %lo(regdump)
  567 
  568     /* 1 */
  569     ori $a1, $a1, GRUB_SMB_RAM_START_ADDR
  570     move $t8, $zero
  571     lui  $t5, 0x0001
  572     bal read_spd
  573      ori $a0, $zero, GRUB_SMBUS_SPD_MEMORY_NUM_BANKS_ADDR
  574     ori $t7, $zero, 8
  575     bne $v0, $t7, 1f
  576      ori $t5, $t5, 0x0001
  577     ori $t8, $t8, GRUB_CPU_LOONGSON_DDR2_REG1_HI_8BANKS
  578 1:
  579     dsll $t8, $t8, 32
  580     or $t5, $t5, $t8
  581     sd  $t5, 0 ($t4)
  582     addiu $t4, $t4, GRUB_CPU_LOONGSON_DDR2_REG_STEP
  583 
  584     /* 2 */
  585     bal write_dumpreg
  586      nop
  587 
  588     /* 3 */
  589     bal write_dumpreg
  590      nop
  591 
  592     /* 4 */
  593     bal write_dumpreg
  594      nop
  595 
  596     /* 5 */
  597     /* FIXME: figure termination resistance.  */
  598     ori $t5, $zero, 0x2
  599     bal read_spd
  600      ori $a0, $zero, GRUB_SMBUS_SPD_MEMORY_NUM_ROWS_ADDR
  601     /* $v0 = 15 - $v0.  */
  602     xori $v0, $v0, 0xf
  603     andi $v0, $v0, 0x7
  604     sll $v0, $v0, 8
  605     or $t5, $t5, $v0
  606 
  607     /* Find the fastest supported CAS latency.  */
  608     bal read_spd
  609      ori $a0, $zero, GRUB_SMBUS_SPD_MEMORY_CAS_LATENCY_ADDR
  610     ori $t0, $zero, GRUB_SMBUS_SPD_MEMORY_CAS_LATENCY_MIN_VALUE
  611     ori $t1, $zero, (1 << GRUB_SMBUS_SPD_MEMORY_CAS_LATENCY_MIN_VALUE)
  612 2:  
  613     and $t2, $t1, $v0
  614     bne $t2, $zero, 1f
  615      ori $t3, $zero, 8
  616     lui $a0, %hi(no_cas_latency)
  617     beq $t0, $t3, fatal
  618      addiu $a0, $a0, %lo(no_cas_latency)
  619     addiu $t0, $t0, 1
  620     b 2b
  621      sll $t1, $t1, 1
  622 1:
  623     sll $t0, $t0, 16
  624     or $t5, $t5, $t0
  625     
  626     bal read_spd
  627      ori $a0, $zero, GRUB_SMBUS_SPD_MEMORY_NUM_COLUMNS_ADDR
  628     /* $v0 = 15 - ($v0 + 1) = 14 - $v0.  */
  629     addiu $v0, $v0, 1
  630     xori $v0, $v0, 0xf
  631     andi $v0, $v0, 0x7
  632     sll $v0, 24
  633     or $t5, $t5, $v0
  634     sd  $t5, 0 ($t4)
  635 
  636     addiu $t4, $t4, GRUB_CPU_LOONGSON_DDR2_REG_STEP
  637     
  638     ori $t7, $zero, 0x16
  639 
  640 1:  
  641     ld $t2, 0($t6)
  642     sd $t2, 0($t4)
  643     addiu $t4, $t4, GRUB_CPU_LOONGSON_DDR2_REG_STEP
  644     addiu $t7, $t7, -1
  645     bne $t7, $zero, 1b
  646      addiu $t6, $t6, GRUB_CPU_LOONGSON_DDR2_REG_SIZE
  647     
  648     lui $t4, %hi(GRUB_CPU_LOONGSON_DDR2_BASE)
  649     ld  $t5, (%lo(GRUB_CPU_LOONGSON_DDR2_BASE) + 0x30) ($t4)
  650     ori $t0, $zero, 1
  651     dsll $t0, $t0, 40
  652     or $t5, $t5, $t0
  653     sd  $t5, (%lo(GRUB_CPU_LOONGSON_DDR2_BASE) + 0x30) ($t4)
  654 
  655     /* Desactivate DDR2 registers.  */
  656         lui $t0, %hi (GRUB_CPU_LOONGSON_CORECFG)
  657         ld  $t1, %lo (GRUB_CPU_LOONGSON_CORECFG) ($t0)
  658     ori $t1, $t1, GRUB_CPU_LOONGSON_CORECFG_DISABLE_DDR2_SPACE
  659         sd  $t1, %lo (GRUB_CPU_LOONGSON_CORECFG) ($t0)
  660 
  661     /* Enable cache.  */
  662     mfc0    $t0, GRUB_CPU_LOONGSON_COP0_CACHE_CONFIG
  663     addiu   $t1, $zero, ~GRUB_CPU_LOONGSON_CACHE_TYPE_MASK
  664     and     $t0, $t1, $t1
  665     /* Set line size to 32 bytes and disabled cache.  */
  666     ori     $t0, $t0, (GRUB_CPU_LOONGSON_COP0_CACHE_CONFIG_ILINESIZE \
  667                        | GRUB_CPU_LOONGSON_COP0_CACHE_CONFIG_DLINESIZE \
  668                        | GRUB_CPU_LOONGSON_CACHE_ACCELERATED)
  669     mtc0    $t0, GRUB_CPU_LOONGSON_COP0_CACHE_CONFIG
  670 
  671     /* Invalidate all I-cache entries.  */
  672     srl $t1, $t0, GRUB_CPU_LOONGSON_COP0_CACHE_ISIZE_SHIFT
  673     andi $t1, $t1, GRUB_CPU_LOONGSON_COP0_CACHE_SIZE_MASK
  674     ori $t2, $zero, (1 << (GRUB_CPU_LOONGSON_COP0_CACHE_SIZE_OFFSET \
  675                            - GRUB_CPU_LOONGSON_CACHE_LINE_SIZE_LOG_BIG \
  676                            - GRUB_CPU_LOONGSON_I_CACHE_LOG_WAYS))
  677     sll $t1, $t2, $t1
  678     lui $t2, 0x8000
  679 
  680 1:  
  681     cache GRUB_CPU_LOONGSON_COP0_I_INDEX_INVALIDATE, 0($t2)
  682     addiu $t1, $t1, -1
  683     bne $t1, $zero, 1b
  684      addiu $t2, $t2, (1 << GRUB_CPU_LOONGSON_COP0_I_INDEX_BIT_OFFSET)
  685 
  686     /* Invalidate all D-cache entries.  */
  687     srl $t1, $t0, GRUB_CPU_LOONGSON_COP0_CACHE_DSIZE_SHIFT
  688     andi $t1, $t1, GRUB_CPU_LOONGSON_COP0_CACHE_SIZE_MASK
  689     ori $t2, $zero, (1 << (GRUB_CPU_LOONGSON_COP0_CACHE_SIZE_OFFSET \
  690                            - GRUB_CPU_LOONGSON_CACHE_LINE_SIZE_LOG_BIG \
  691                            - GRUB_CPU_LOONGSON_D_CACHE_LOG_WAYS))
  692     sll $t1, $t2, $t1
  693     lui $t2, 0x8000
  694     mtc0 $zero, GRUB_CPU_LOONGSON_COP0_CACHE_TAGLO
  695     mtc0 $zero, GRUB_CPU_LOONGSON_COP0_CACHE_TAGHI
  696 1:
  697     /* All four ways.  */
  698     cache GRUB_CPU_LOONGSON_COP0_D_INDEX_TAG_STORE, 0($t2)
  699     cache GRUB_CPU_LOONGSON_COP0_D_INDEX_TAG_STORE, 1($t2)
  700     cache GRUB_CPU_LOONGSON_COP0_D_INDEX_TAG_STORE, 2($t2)
  701     cache GRUB_CPU_LOONGSON_COP0_D_INDEX_TAG_STORE, 3($t2)
  702     addiu $t1, $t1, -1
  703     bne $t1, $zero, 1b
  704      addiu $t2, $t2, (1 << GRUB_CPU_LOONGSON_COP0_D_INDEX_BIT_OFFSET)
  705 
  706     /* Invalidate all S-cache entries.  */
  707     ori $t1, $zero, (1 << (GRUB_CPU_LOONGSON_SECONDARY_CACHE_LOG_SIZE \
  708                            - GRUB_CPU_LOONGSON_CACHE_LINE_SIZE_LOG_BIG \
  709                            - GRUB_CPU_LOONGSON_S_CACHE_LOG_WAYS))
  710     lui $t2, 0x8000
  711     mtc0 $zero, GRUB_CPU_LOONGSON_COP0_CACHE_TAGLO
  712     mtc0 $zero, GRUB_CPU_LOONGSON_COP0_CACHE_TAGHI
  713 1:
  714     /* All four ways.  */
  715     cache GRUB_CPU_LOONGSON_COP0_S_INDEX_TAG_STORE, 0($t2)
  716     cache GRUB_CPU_LOONGSON_COP0_S_INDEX_TAG_STORE, 1($t2)
  717     cache GRUB_CPU_LOONGSON_COP0_S_INDEX_TAG_STORE, 2($t2)
  718     cache GRUB_CPU_LOONGSON_COP0_S_INDEX_TAG_STORE, 3($t2)
  719     addiu $t1, $t1, -1
  720     bne $t1, $zero, 1b
  721      addiu $t2, $t2, (1 << GRUB_CPU_LOONGSON_COP0_D_INDEX_BIT_OFFSET)
  722     
  723     /* Finally enable cache.  */
  724     mfc0    $t0, GRUB_CPU_LOONGSON_COP0_CACHE_CONFIG
  725     addiu   $t1, $zero, ~GRUB_CPU_LOONGSON_CACHE_TYPE_MASK
  726     and     $t0, $t1, $t1
  727     ori     $t0, $t0, GRUB_CPU_LOONGSON_CACHE_CACHED
  728     mtc0    $t0, GRUB_CPU_LOONGSON_COP0_CACHE_CONFIG
  729 
  730     lui $a0, %hi(caches_enabled)
  731     bal message
  732       addiu $a0, $a0, %lo(caches_enabled)
  733 
  734     /* Set ROM delay cycles to 1.  */
  735     lui $t0, %hi(GRUB_CPU_LOONGSON_LIOCFG)
  736     lw  $t1, %lo(GRUB_CPU_LOONGSON_LIOCFG) ($t0)
  737     addiu $t2, $zero, ~(GRUB_CPU_LOONGSON_ROM_DELAY_MASK \
  738                         << GRUB_CPU_LOONGSON_ROM_DELAY_OFFSET)
  739     and $t1, $t1, $t2
  740     ori $t1, $t1, (1 << GRUB_CPU_LOONGSON_ROM_DELAY_OFFSET)
  741     sw  $t1, %lo(GRUB_CPU_LOONGSON_LIOCFG) ($t0)
  742     
  743     addiu $a0, $zero, -1
  744     addiu $a1, $zero, -1
  745 
  746     /* Take advantage of cache.  */
  747     lui $t0, %hi(cached_continue - 0x20000000)
  748     addiu $t0, $t0, %lo(cached_continue - 0x20000000)
  749     jr $t0
  750 #ifdef FULOONG2F
  751      addiu $a2, $zero, -(1 + GRUB_ARCH_MACHINE_FULOONG2F)
  752 #else
  753      addiu $a2, $zero, -(1 + GRUB_ARCH_MACHINE_YEELOONG)
  754 #endif
  755 
  756 cached_continue:
  757 #ifndef FULOONG2F
  758     /* We have to init video early enough or watchdog will reboot us.  */
  759 
  760         /* Setup PCI controller.  */
  761 
  762     lui    $t0, %hi (GRUB_CPU_LOONGSON_PCI_HIT1_SEL_LO)
  763     lui    $t1, %hi(0x8000000c)
  764     addiu  $t1, $t1, %lo(0x8000000c)
  765 
  766     sw  $t1, %lo (GRUB_CPU_LOONGSON_PCI_HIT1_SEL_LO) ($t0)
  767     li  $t1, 0xffffffff
  768     sw  $t1, %lo (GRUB_CPU_LOONGSON_PCI_HIT1_SEL_HI) ($t0)
  769 
  770     li  $t0, GRUB_MACHINE_PCI_CONTROLLER_HEADER
  771     li  $t1, (GRUB_PCI_COMMAND_PARITY_ERROR | GRUB_PCI_COMMAND_BUS_MASTER \
  772                   | GRUB_PCI_COMMAND_MEM_ENABLED)
  773     sh  $t0, GRUB_PCI_REG_COMMAND ($t1)
  774     li  $t1, ((1 << GRUB_PCI_STATUS_DEVSEL_TIMING_SHIFT) \
  775                   | GRUB_PCI_STATUS_FAST_B2B_CAPABLE         \
  776               | GRUB_PCI_STATUS_66MHZ_CAPABLE            \
  777                   | GRUB_PCI_STATUS_CAPABILITIES)
  778     sh  $t0, GRUB_PCI_REG_STATUS ($t1)
  779     li  $t0, 0xff
  780     sw  $t0, GRUB_PCI_REG_CACHELINE ($t1)
  781     lui  $t1, %hi(0x80000000 | GRUB_PCI_ADDR_MEM_TYPE_64 \
  782                   | GRUB_PCI_ADDR_MEM_PREFETCH)
  783     addiu  $t1, $t1,  %lo(0x80000000 | GRUB_PCI_ADDR_MEM_TYPE_64 \
  784                           | GRUB_PCI_ADDR_MEM_PREFETCH)
  785     sw  $t0, GRUB_PCI_REG_ADDRESS_REG0 ($t1)
  786     sw  $zero, GRUB_PCI_REG_ADDRESS_REG1 ($t1)
  787 
  788     /* Find video.  */
  789     /* $t4 chooses device in priority encoding.  */
  790     /* Resulting value is kept in GRUB_MACHINE_PCI_CONF_CTRL_REG.
  791        This way we don't need to sacrifice a register for it.  */
  792 retry_sm712:
  793     /* We have only one bus (0). Function is 0.  */
  794     lui $t0, %hi(GRUB_MACHINE_PCI_CONF_CTRL_REG_ADDR)
  795     lui $t1, %hi(GRUB_MACHINE_PCI_CONFSPACE)
  796     lui $t3, %hi(GRUB_SM712_PCIID)
  797     addiu $t3, $t3, %lo(GRUB_SM712_PCIID)
  798     ori $t4, $zero, 1
  799 1:
  800     andi $t4, $t4, ((1 << GRUB_PCI_NUM_DEVICES) - 1)
  801     /* In case of failure try again. SM712 may be slow to come up.  */
  802     beql  $t4, $zero, retry_sm712
  803      nop
  804     sw   $t4, %lo(GRUB_MACHINE_PCI_CONF_CTRL_REG_ADDR) ($t0)
  805     lw   $t2, (%lo(GRUB_MACHINE_PCI_CONFSPACE) + GRUB_PCI_REG_PCI_ID) ($t1)
  806     bnel  $t2, $t3, 1b
  807      sll $t4, $t4, 1
  808 
  809     /* FIXME: choose address dynamically if needed.   */
  810 #define SM712_MAP 0x04000000
  811     
  812     lui  $t2, %hi(SM712_MAP)
  813     sw   $t4, %lo(GRUB_MACHINE_PCI_CONF_CTRL_REG_ADDR) ($t0)
  814     sw   $t2, (%lo(GRUB_MACHINE_PCI_CONFSPACE) + GRUB_PCI_REG_ADDRESS_REG0) ($t1)
  815 
  816     /* Set latency.  */
  817     li   $t2, 0x8
  818     sw   $t4, %lo(GRUB_MACHINE_PCI_CONF_CTRL_REG_ADDR) ($t0)
  819     sw   $t2, (%lo(GRUB_MACHINE_PCI_CONFSPACE) + GRUB_PCI_REG_CACHELINE) ($t1)
  820 
  821     /* Enable address spaces.  */
  822     li   $t2, 0x7
  823     sw   $t4, %lo(GRUB_MACHINE_PCI_CONF_CTRL_REG_ADDR) ($t0)
  824     sw   $t2, (%lo(GRUB_MACHINE_PCI_CONFSPACE) + GRUB_PCI_REG_COMMAND) ($t1)
  825 
  826     lui   $t3, %hi(GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_SR_INDEX)
  827     li   $t2, 0x18
  828     sb   $t2, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_SR_INDEX)($t3)
  829 
  830     lui   $t3, %hi(GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_SR_DATA)
  831     li   $t2, 0x11
  832     sb   $t2, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_SR_DATA)($t3)
  833 
  834     li   $t2, ((((SM712_MAP & ~GRUB_MACHINE_PCI_WIN_OFFSET_MASK) \
  835                  >> GRUB_MACHINE_PCI_WIN_SHIFT)                  \
  836                & GRUB_MACHINE_PCI_WIN_MASK))
  837     lui   $t3, %hi(0xbfe00110)
  838     addiu   $t3, $t3, %lo(0xbfe00110)
  839     sw   $t2, 0 ($t3)
  840     li   $t2, (GRUB_MACHINE_PCI_WIN1_ADDR                        \
  841                | (SM712_MAP & GRUB_MACHINE_PCI_WIN_OFFSET_MASK))
  842 
  843     lui   $t3, %hi(GRUB_SM712_REG_BASE)
  844     addiu $t3, $t3, %lo(GRUB_SM712_REG_BASE)
  845     addu  $t2, $t2, $t3
  846     lui   $t0, %hi(init_table - 0x20000000)
  847     addiu $t0, $t0, %lo(init_table - 0x20000000)
  848     lui   $t1, %hi(init_table_end - 0x20000000)
  849     addiu $t1, $t1, %lo(init_table_end - 0x20000000)
  850     li    $t5, 0x80
  851     addiu $t6, $t2, 0x3c0
  852 
  853 table_cont: 
  854     lb    $t3, 0($t0)
  855     andi  $t5, $t3, 0x80
  856     andi  $t3, $t3, 0x7f
  857     addu  $t3, $t3, $t6
  858     lb    $t4, 1($t0)
  859 
  860     bne   $zero, $t5, 1f
  861          addiu $t0, $t0, 2
  862         b  2f
  863      sb    $t4, 0($t3)
  864 1:  
  865     lb    $t4, 0($t3)
  866 2:  
  867     bne   $t0, $t1, table_cont
  868          nop
  869 
  870     lui   $t3, %hi(0x40c000 - GRUB_SM712_REG_BASE)
  871     addiu $t3, $t3, %lo(0x40c000 - GRUB_SM712_REG_BASE)
  872     addu  $t1, $t2, $t3 
  873     sw    $zero, 0xc ($t1)
  874     sw    $zero, 0x40 ($t1)
  875     li    $t3, 0x20000
  876     sw    $t3, 0x0 ($t1)
  877     lui   $t3, %hi(0x1020100)
  878     addiu $t3, $t3, %lo(0x1020100)
  879     sw    $t3, 0x10 ($t1)
  880 
  881     li    $t4, 0x16
  882         sb    $t4, GRUB_VGA_IO_SR_INDEX($t2)
  883 
  884         lb    $t4, GRUB_VGA_IO_SR_DATA($t2)
  885 
  886     b init_end
  887       nop
  888 init_table: 
  889 #include "sm712_start.S"
  890 init_table_end:
  891     .align 4
  892 init_end:   
  893 #endif