123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742 |
- /*
- * (C) Copyright 2001
- * Bill Hunter, Wave 7 Optics, william.hunter@mediaone.net
- * and
- * Erik Theisen, Wave 7 Optics, etheisen@mindspring.com
- *
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
- */
- /*
- * Description:
- * Routine to exercise memory for the bringing up of our boards.
- */
- #include <config.h>
- #include <ppc4xx.h>
- #define _LINUX_CONFIG_H 1 /* avoid reading Linux autoconf.h file */
- #include <ppc_asm.tmpl>
- #include <ppc_defs.h>
- #include <asm/cache.h>
- #include <asm/mmu.h>
- #include <watchdog.h>
- #include "errors.h"
- #define _ASMLANGUAGE
- .globl test_sdram
- .globl test_led
- .globl log_stat
- .globl log_warn
- .globl log_err
- .globl temp_uart_init
- .globl post_puts
- .globl disp_hex
- /*****************************************************
- ******* Text Strings for low level printing ******
- ******* In section got2 *******
- *****************************************************/
- /*
- * Define the text strings for errors and warnings.
- * Switch to .data section.
- */
- .section ".data"
- err_str: .asciz "*** POST ERROR = "
- warn_str: .asciz "*** POST WARNING = "
- end_str: .asciz "\r\n"
- /*
- * Enter the labels in Global Entry Table (GOT).
- * Switch to .got2 section.
- */
- START_GOT
- GOT_ENTRY(err_str)
- GOT_ENTRY(warn_str)
- GOT_ENTRY(end_str)
- END_GOT
- /*
- * Switch back to .text section.
- */
- .text
- /****************************************
- ****************************************
- ******** LED register test ********
- ****************************************
- ***************************************/
- test_led:
- /* save the return info on stack */
- mflr r0 /* Get link register */
- stwu r1, -12(r1) /* Save back chain and move SP */
- stw r0, +16(r1) /* Save link register */
- stw r4, +8(r1) /* save R4 */
- WATCHDOG_RESET /* Reset the watchdog */
- addi r3, 0, ERR_FF /* first test value is ffff */
- addi r4, r3, 0 /* save copy of pattern */
- bl set_led /* store first test value */
- bl get_led /* read it back */
- xor. r4, r4, r3 /* compare to original */
- #if defined(CONFIG_W7OLMC)
- andi. r4, r4, 0x00ff /* lmc has 8 bits */
- #else
- andi. r4, r4, 0xffff /* lmg has 16 bits */
- #endif
- beq LED2 /* next test */
- addi r3, 0, ERR_LED /* error code = 1 */
- bl log_err /* display error and halt */
- LED2: addi r3, 0, ERR_00 /* 2nd test value is 0000 */
- addi r4, r3, 0 /* save copy of pattern */
- bl set_led /* store first test value */
- bl get_led /* read it back */
- xor. r4, r4, r3 /* compare to original */
- #if defined(CONFIG_W7OLMC)
- andi. r4, r4, 0x00ff /* lmc has 8 bits */
- #else
- andi. r4, r4, 0xffff /* lmg has 16 bits */
- #endif
- beq LED3 /* next test */
- addi r3, 0, ERR_LED /* error code = 1 */
- bl log_err /* display error and halt */
- LED3: /* restore stack and return */
- lwz r0, +16(r1) /* Get saved link register */
- mtlr r0 /* Restore link register */
- lwz r4, +8(r1) /* restore r4 */
- addi r1, r1, +12 /* Remove frame from stack */
- blr /* Return to calling function */
- /****************************************
- ****************************************
- ******** SDRAM TESTS ********
- ****************************************
- ***************************************/
- test_sdram:
- /* called with mem size in r3 */
- /* save the return info on stack */
- mflr r0 /* Get link register */
- stwu r1, -16(r1) /* Save back chain and move SP */
- stw r0, +20(r1) /* Save link register */
- stmw r30, +8(r1) /* save R30,R31 */
- /* r30 is log2(mem size) */
- /* r31 is mem size */
- /* take log2 of total mem size */
- addi r31, r3, 0 /* save total mem size */
- addi r30, 0, 0 /* clear r30 */
- l2_loop:
- srwi. r31, r31, 1 /* shift right 1 */
- addi r30, r30, 1 /* count shifts */
- bne l2_loop /* loop till done */
- addi r30, r30, -1 /* correct for over count */
- addi r31, r3, 0 /* save original size */
- /* now kick the dog and test the mem */
- WATCHDOG_RESET /* Reset the watchdog */
- bl Data_Buster /* test crossed/shorted data lines */
- addi r3, r30, 0 /* get log2(memsize) */
- addi r4, r31, 0 /* get memsize */
- bl Ghost_Buster /* test crossed/shorted addr lines */
- addi r3, r31, 0 /* get mem size */
- bl Bit_Buster /* check for bad internal bits */
- /* restore stack and return */
- lmw r30, +8(r1) /* Restore r30, r31 */
- lwz r0, +20(r1) /* Get saved link register */
- mtlr r0 /* Restore link register */
- addi r1, r1, +16 /* Remove frame from stack */
- blr /* Return to calling function */
- /****************************************
- ******** sdram data bus test ********
- ***************************************/
- Data_Buster:
- /* save the return info on stack */
- mflr r0 /* Get link register */
- stwu r1, -24(r1) /* Save back chain and move SP */
- stw r0, +28(r1) /* Save link register */
- stmw r28, 8(r1) /* save r28 - r31 on stack */
- /* r31 i/o register */
- /* r30 sdram base address */
- /* r29 5555 syndrom */
- /* r28 aaaa syndrom */
- /* set up led register for this test */
- addi r3, 0, ERR_RAMG /* set led code to 1 */
- bl log_stat /* store test value */
- /* now test the dram data bus */
- xor r30, r30, r30 /* load r30 with base addr of sdram */
- addis r31, 0, 0x5555 /* load r31 with test value */
- ori r31, r31, 0x5555
- stw r31,0(r30) /* sto the value */
- lwz r29,0(r30) /* read it back */
- xor r29,r31,r29 /* compare it to original */
- addis r31, 0, 0xaaaa /* load r31 with test value */
- ori r31, r31, 0xaaaa
- stw r31,0(r30) /* sto the value */
- lwz r28,0(r30) /* read it back */
- xor r28,r31,r28 /* compare it to original */
- or r3,r28,r29 /* or together both error terms */
- /*
- * Now that we have the error bits,
- * we have to decide which part they are in.
- */
- bl get_idx /* r5 is now index to error */
- addi r3, r3, ERR_RAMG
- cmpwi r3, ERR_RAMG /* check for errors */
- beq db_done /* skip if no errors */
- bl log_err /* log the error */
- db_done:
- lmw r28, 8(r1) /* restore r28 - r31 from stack */
- lwz r0, +28(r1) /* Get saved link register */
- addi r1, r1, +24 /* Remove frame from stack */
- mtlr r0 /* Restore link register */
- blr /* Return to calling function */
- /****************************************************
- ******** test for address ghosting in dram ********
- ***************************************************/
- Ghost_Buster:
- /* save the return info on stack */
- mflr r0 /* Get link register */
- stwu r1, -36(r1) /* Save back chain and move SP */
- stw r0, +40(r1) /* Save link register */
- stmw r25, 8(r1) /* save r25 - r31 on stack */
- /* r31 = scratch register */
- /* r30 is main referance loop counter,
- 0 to 23 */
- /* r29 is ghost loop count, 0 to 22 */
- /* r28 is referance address */
- /* r27 is ghost address */
- /* r26 is log2 (mem size) =
- number of byte addr bits */
- /* r25 is mem size */
- /* save the log2(mem size) and mem size */
- addi r26, r3, 0 /* r26 is number of byte addr bits */
- addi r25, r4, 0 /* r25 is mem size in bytes */
- /* set the leds for address ghost test */
- addi r3, 0, ERR_ADDG
- bl set_led
- /* first fill memory with zeros */
- srwi r31, r25, 2 /* convert bytes to longs */
- mtctr r31 /* setup byte counter */
- addi r28, 0, 0 /* start at address at 0 */
- addi r31, 0, 0 /* data value = 0 */
- clr_loop:
- stw r31, 0(r28) /* Store zero value */
- addi r28, r28, 4 /* Increment to next word */
- andi. r27, r28, 0xffff /* check for 2^16 loops */
- bne clr_skip /* if not there, then skip */
- WATCHDOG_RESET /* kick the dog every now and then */
- clr_skip:
- bdnz clr_loop /* Round and round... */
- /* now do main test */
- addi r30, 0, 0 /* start referance counter at 0 */
- outside:
- /*
- * Calculate the referance address
- * the referance address is calculated by setting the (r30-1)
- * bit of the base address
- * when r30=0, the referance address is the base address.
- * thus the sequence 0,1,2,4,8,..,2^(n-1)
- * setting the bit is done with the following shift functions.
- */
- WATCHDOG_RESET /* Reset the watchdog */
- addi r31, 0, 1 /* r31 = 1 */
- slw r28, r31, r30 /* set bit coresponding to loop cnt */
- srwi r28, r28, 1 /* then shift it right one so */
- /* we start at location 0 */
- /* fill referance address with Fs */
- addi r31, 0, 0x00ff /* r31 = one byte of set bits */
- stb r31,0(r28) /* save ff in referance address */
- /* ghost (inner) loop, now check all posible ghosted addresses */
- addi r29, 0, 0 /* start ghosted loop counter at 0 */
- inside:
- /*
- * Calculate the ghost address by flipping one
- * bit of referance address. This gives the
- * sequence 1,2,4,8,...,2^(n-1)
- */
- addi r31, 0, 1 /* r31 = 1 */
- slw r27, r31, r29 /* set bit coresponding to loop cnt */
- xor r27, r28, r27 /* ghost address = ref addr with
- bit flipped*/
- /* now check for ghosting */
- lbz r31,0(r27) /* get content of ghost addr */
- cmpwi r31, 0 /* compare read value to 0 */
- bne Casper /* we found a ghost! */
- /* now close ghost ( inner ) loop */
- addi r29, r29, 1 /* increment inner loop counter */
- cmpw r29, r26 /* check for last inner loop */
- blt inside /* do more inner loops */
- /* now close referance ( outer ) loop */
- addi r31, 0, 0 /* r31 = zero */
- stb r31, 0(28) /* zero out the altered address loc. */
- /*
- * Increment and check for end, count is zero based.
- * With the ble, this gives us one more loops than
- * address bits for sequence 0,1,2,4,8,...2^(n-1)
- */
- addi r30, r30, 1 /* increment outer loop counter */
- cmpw r30, r26 /* check for last inner loop */
- ble outside /* do more outer loops */
- /* were done, lets go home */
- b gb_done
- Casper: /* we found a ghost !! */
- addi r3, 0, ERR_ADDF /* get indexed error message */
- bl log_err /* log error led error code */
- gb_done: /* pack your bags, and go home */
- lmw r25, 8(r1) /* restore r25 - r31 from stack */
- lwz r0, +40(r1) /* Get saved link register */
- addi r1, r1, +36 /* Remove frame from stack */
- mtlr r0 /* Restore link register */
- blr /* Return to calling function */
- /****************************************************
- ******** SDRAM data fill tests **********
- ***************************************************/
- Bit_Buster:
- /* called with mem size in r3 */
- /* save the return info on stack */
- mflr r0 /* Get link register */
- stwu r1, -16(r1) /* Save back chain and move SP */
- stw r0, +20(r1) /* Save link register */
- stw r4, +8(r1) /* save R4 */
- stw r5, +12(r1) /* save r5 */
- addis r5, r3, 0 /* save mem size */
- /* Test 55555555 */
- addi r3, 0, ERR_R55G /* set up error code in case we fail */
- bl log_stat /* store test value */
- addis r4, 0, 0x5555
- ori r4, r4, 0x5555
- bl fill_test
- /* Test aaaaaaaa */
- addi r3, 0, ERR_RAAG /* set up error code in case we fail */
- bl log_stat /* store test value */
- addis r4, 0, 0xAAAA
- ori r4, r4, 0xAAAA
- bl fill_test
- /* Test 00000000 */
- addi r3, 0, ERR_R00G /* set up error code in case we fail */
- bl log_stat /* store test value */
- addis r4, 0, 0
- ori r4, r4, 0
- bl fill_test
- /* restore stack and return */
- lwz r5, +12(r1) /* restore r4 */
- lwz r4, +8(r1) /* restore r4 */
- lwz r0, +20(r1) /* Get saved link register */
- addi r1, r1, +16 /* Remove frame from stack */
- mtlr r0 /* Restore link register */
- blr /* Return to calling function */
- /****************************************************
- ******** fill test ********
- ***************************************************/
- /* tests memory by filling with value, and reading back */
- /* r5 = Size of memory in bytes */
- /* r4 = Value to write */
- /* r3 = Error code */
- fill_test:
- mflr r0 /* Get link register */
- stwu r1, -32(r1) /* Save back chain and move SP */
- stw r0, +36(r1) /* Save link register */
- stmw r27, 8(r1) /* save r27 - r31 on stack */
- /* r31 - scratch register */
- /* r30 - memory address */
- mr r27, r3
- mr r28, r4
- mr r29, r5
- WATCHDOG_RESET /* Reset the watchdog */
- /* first fill memory with Value */
- srawi r31, r29, 2 /* convert bytes to longs */
- mtctr r31 /* setup counter */
- addi r30, 0, 0 /* Make r30 = addr 0 */
- ft_0: stw r28, 0(r30) /* Store value */
- addi r30, r30, 4 /* Increment to next word */
- andi. r31, r30, 0xffff /* check for 2^16 loops */
- bne ft_0a /* if not there, then skip */
- WATCHDOG_RESET /* kick the dog every now and then */
- ft_0a: bdnz ft_0 /* Round and round... */
- WATCHDOG_RESET /* Reset the watchdog */
- /* Now confirm Value is in memory */
- srawi r31, r29, 2 /* convert bytes to longs */
- mtctr r31 /* setup counter */
- addi r30, 0, 0 /* Make r30 = addr 0 */
- ft_1: lwz r31, 0(r30) /* get value from memory */
- xor. r31, r31, r28 /* Writen = Read ? */
- bne ft_err /* If bad, than halt */
- addi r30, r30, 4 /* Increment to next word */
- andi. r31, r30, 0xffff /* check for 2^16 loops*/
- bne ft_1a /* if not there, then skip */
- WATCHDOG_RESET /* kick the dog every now and then */
- ft_1a: bdnz ft_1 /* Round and round... */
- WATCHDOG_RESET /* Reset the watchdog */
- b fill_done /* restore and return */
- ft_err: addi r29, r27, 0 /* save current led code */
- addi r27, r31, 0 /* get pattern in r27 */
- bl get_idx /* get index from r27 */
- add r27, r27, r29 /* add index to old led code */
- bl log_err /* output led err code, halt CPU */
- fill_done:
- lmw r27, 8(r1) /* restore r27 - r31 from stack */
- lwz r0, +36(r1) /* Get saved link register */
- addi r1, r1, +32 /* Remove frame from stack */
- mtlr r0 /* Restore link register */
- blr /* Return to calling function */
- /****************************************************
- ******* get error index from r3 pattern ********
- ***************************************************/
- get_idx: /* r3 = (MSW(r3) !=0)*2 +
- (LSW(r3) !=0) */
- /* save the return info on stack */
- mflr r0 /* Get link register */
- stwu r1, -12(r1) /* Save back chain and move SP */
- stw r0, +16(r1) /* Save link register */
- stw r4, +8(r1) /* save R4 */
- andi. r4, r3, 0xffff /* check for lower bits */
- beq gi2 /* skip if no bits set */
- andis. r4, r3, 0xffff /* check for upper bits */
- beq gi3 /* skip if no bits set */
- addi r3, 0, 3 /* both upper and lower bits set */
- b gi_done
- gi2: andis. r4, r3, 0xffff /* check for upper bits*/
- beq gi4 /* skip if no bits set */
- addi r3, 0, 2 /* only upper bits set */
- b gi_done
- gi3: addi r3, 0, 1 /* only lower bits set */
- b gi_done
- gi4: addi r3, 0, 0 /* no bits set */
- gi_done:
- /* restore stack and return */
- lwz r0, +16(r1) /* Get saved link register */
- mtlr r0 /* Restore link register */
- lwz r4, +8(r1) /* restore r4 */
- addi r1, r1, +12 /* Remove frame from stack */
- blr /* Return to calling function */
- /****************************************************
- ******** set LED to R5 and hang ********
- ***************************************************/
- log_stat: /* output a led code and continue */
- set_led:
- /* save the return info on stack */
- mflr r0 /* Get link register */
- stwu r1, -12(r1) /* Save back chain and move SP */
- stw r0, +16(r1) /* Save link register */
- stw r4, +8(r1) /* save R4 */
- addis r4, 0, 0xfe00 /* LED buffer is at 0xfe000000 */
- #if defined(CONFIG_W7OLMG) /* only on gateway, invert outputs */
- xori r3,r3, 0xffff /* complement led code, active low */
- sth r3, 0(r4) /* store first test value */
- xori r3,r3, 0xffff /* complement led code, active low */
- #else /* if not gateway, then don't invert */
- sth r3, 0(r4) /* store first test value */
- #endif
- /* restore stack and return */
- lwz r0, +16(r1) /* Get saved link register */
- mtlr r0 /* Restore link register */
- lwz r4, +8(r1) /* restore r4 */
- addi r1, r1, +12 /* Remove frame from stack */
- blr /* Return to calling function */
- get_led:
- /* save the return info on stack */
- mflr r0 /* Get link register */
- stwu r1, -12(r1) /* Save back chain and move SP */
- stw r0, +16(r1) /* Save link register */
- stw r4, +8(r1) /* save R4 */
- addis r4, 0, 0xfe00 /* LED buffer is at 0xfe000000 */
- lhz r3, 0(r4) /* store first test value */
- #if defined(CONFIG_W7OLMG) /* only on gateway, invert inputs */
- xori r3,r3, 0xffff /* complement led code, active low */
- #endif
- /* restore stack and return */
- lwz r0, +16(r1) /* Get saved link register */
- mtlr r0 /* Restore link register */
- lwz r4, +8(r1) /* restore r4 */
- addi r1, r1, +12 /* Remove frame from stack */
- blr /* Return to calling function */
- log_err: /* output the error and hang the board ( for now ) */
- /* save the return info on stack */
- mflr r0 /* Get link register */
- stwu r1, -12(r1) /* Save back chain and move SP */
- stw r0, +16(r1) /* Save link register */
- stw r3, +8(r1) /* save a copy of error code */
- bl set_led /* set the led pattern */
- GET_GOT /* get GOT address in r14 */
- lwz r3,GOT(err_str) /* get address of string */
- bl post_puts /* output the warning string */
- lwz r3, +8(r1) /* get error code */
- addi r4, 0, 2 /* set disp length to 2 nibbles */
- bl disp_hex /* output the error code */
- lwz r3,GOT(end_str) /* get address of string */
- bl post_puts /* output the warning string */
- halt:
- b halt /* hang */
- /* restore stack and return */
- lwz r0, +16(r1) /* Get saved link register */
- mtlr r0 /* Restore link register */
- addi r1, r1, +12 /* Remove frame from stack */
- blr /* Return to calling function */
- log_warn: /* output a warning, then continue with operations */
- /* save the return info on stack */
- mflr r0 /* Get link register */
- stwu r1, -16(r1) /* Save back chain and move SP */
- stw r0, +20(r1) /* Save link register */
- stw r3, +8(r1) /* save a copy of error code */
- stw r14, +12(r1) /* save a copy of r14 (used by GOT) */
- bl set_led /* set the led pattern */
- GET_GOT /* get GOT address in r14 */
- lwz r3,GOT(warn_str) /* get address of string */
- bl post_puts /* output the warning string */
- lwz r3, +8(r1) /* get error code */
- addi r4, 0, 2 /* set disp length to 2 nibbles */
- bl disp_hex /* output the error code */
- lwz r3,GOT(end_str) /* get address of string */
- bl post_puts /* output the warning string */
- addis r3, 0, 64 /* has a long delay */
- mtctr r3
- log_2:
- WATCHDOG_RESET /* this keeps dog from barking, */
- /* and takes time */
- bdnz log_2 /* loop till time expires */
- /* restore stack and return */
- lwz r0, +20(r1) /* Get saved link register */
- lwz r14, +12(r1) /* restore r14 */
- mtlr r0 /* Restore link register */
- addi r1, r1, +16 /* Remove frame from stack */
- blr /* Return to calling function */
- /*******************************************************************
- * temp_uart_init
- * Temporary UART initialization routine
- * Sets up UART0 to run at 9600N81 off of the internal clock.
- * R3-R4 are used.
- ******************************************************************/
- temp_uart_init:
- /* save the return info on stack */
- mflr r0 /* Get link register */
- stwu r1, -8(r1) /* Save back chain and move SP */
- stw r0, +12(r1) /* Save link register */
- addis r3, 0, 0xef60
- ori r3, r3, 0x0303 /* r3 = UART0_LCR */
- addi r4, 0, 0x83 /* n81 format, divisor regs enabled */
- stb r4, 0(r3)
- /* set baud rate to use internal clock,
- baud = (200e6/16)/31/42 = 9600 */
- addis r3, 0, 0xef60 /* Address of baud divisor reg */
- ori r3, r3, 0x0300 /* UART0_DLM */
- addi r4, 0, +42 /* uart baud divisor LSB = 93 */
- stb r4, 0(r3) /* baud = (200 /16)/14/93 */
- addi r3, r3, 0x0001 /* uart baud divisor addr */
- addi r4, 0, 0
- stb r4, 0(r3) /* Divisor Latch MSB = 0 */
- addis r3, 0, 0xef60
- ori r3, r3, 0x0303 /* r3 = UART0_LCR */
- addi r4, 0, 0x03 /* n81 format, tx/rx regs enabled */
- stb r4, 0(r3)
- /* output a few line feeds */
- addi r3, 0, '\n' /* load line feed */
- bl post_putc /* output the char */
- addi r3, 0, '\n' /* load line feed */
- bl post_putc /* output the char */
- /* restore stack and return */
- lwz r0, +12(r1) /* Get saved link register */
- mtlr r0 /* Restore link register */
- addi r1, r1, +8 /* Remove frame from stack */
- blr /* Return to calling function */
- /**********************************************************************
- ** post_putc
- ** outputs charactor in R3
- ** r3 returns the error code ( -1 if there is an error )
- *********************************************************************/
- post_putc:
- /* save the return info on stack */
- mflr r0 /* Get link register */
- stwu r1, -20(r1) /* Save back chain and move SP */
- stw r0, +24(r1) /* Save link register */
- stmw r29, 8(r1) /* save r29 - r31 on stack
- r31 - uart base address
- r30 - delay counter
- r29 - scratch reg */
- addis r31, 0, 0xef60 /* Point to uart base */
- ori r31, r31, 0x0300
- addis r30, 0, 152 /* Load about 10,000,000 ticks. */
- pputc_lp:
- lbz r29, 5(r31) /* Read Line Status Register */
- andi. r29, r29, 0x20 /* Check THRE status */
- bne thre_set /* Branch if FIFO empty */
- addic. r30, r30, -1 /* Decrement and check if empty. */
- bne pputc_lp /* Try, try again */
- addi r3, 0, -1 /* Load error code for timeout */
- b pputc_done /* Bail out with error code set */
- thre_set:
- stb r3, 0(r31) /* Store character to UART */
- addi r3, 0, 0 /* clear error code */
- pputc_done:
- lmw r29, 8(r1) /*restore r29 - r31 from stack */
- lwz r0, +24(r1) /* Get saved link register */
- addi r1, r1, +20 /* Remove frame from stack */
- mtlr r0 /* Restore link register */
- blr /* Return to calling function */
- /****************************************************************
- post_puts
- Accepts a null-terminated string pointed to by R3
- Outputs to the serial port until 0x00 is found.
- r3 returns the error code ( -1 if there is an error )
- *****************************************************************/
- post_puts:
- /* save the return info on stack */
- mflr r0 /* Get link register */
- stwu r1, -12(r1) /* Save back chain and move SP */
- stw r0, +16(r1) /* Save link register */
- stw r31, 8(r1) /* save r31 - char pointer */
- addi r31, r3, 0 /* move pointer to R31 */
- pputs_nxt:
- lbz r3, 0(r31) /* Get next character */
- addic. r3, r3, 0 /* Check for zero */
- beq pputs_term /* bail out if zero */
- bl post_putc /* output the char */
- addic. r3, r3, 0 /* check for error */
- bne pputs_err
- addi r31, r31, 1 /* point to next char */
- b pputs_nxt /* loop till term */
- pputs_err:
- addi r3, 0, -1 /* set error code */
- b pputs_end /* were outa here */
- pputs_term:
- addi r3, 0, 1 /* set success code */
- /* restore stack and return */
- pputs_end:
- lwz r31, 8(r1) /* restore r27 - r31 from stack */
- lwz r0, +16(r1) /* Get saved link register */
- addi r1, r1, +12 /* Remove frame from stack */
- mtlr r0 /* Restore link register */
- blr /* Return to calling function */
- /********************************************************************
- ***** disp_hex
- ***** Routine to display a hex value from a register.
- ***** R3 is value to display
- ***** R4 is number of nibbles to display ie 2 for byte 8 for (long)word
- ***** Returns -1 in R3 if there is an error ( ie serial port hangs )
- ***** Returns 0 in R3 if no error
- *******************************************************************/
- disp_hex:
- /* save the return info on stack */
- mflr r0 /* Get link register */
- stwu r1, -16(r1) /* Save back chain and move SP */
- stw r0, +20(r1) /* Save link register */
- stmw r30, 8(r1) /* save r30 - r31 on stack */
- /* r31 output char */
- /* r30 uart base address */
- addi r30, 0, 8 /* Go through 8 nibbles. */
- addi r31, r3, 0
- pputh_nxt:
- rlwinm r31, r31, 4, 0, 31 /* Rotate next nibble into position */
- andi. r3, r31, 0x0f /* Get nibble. */
- addi r3, r3, 0x30 /* Add zero's ASCII code. */
- cmpwi r3, 0x03a
- blt pputh_out
- addi r3, r3, 0x07 /* 0x27 for lower case. */
- pputh_out:
- cmpw r30, r4
- bgt pputh_skip
- bl post_putc
- addic. r3, r3, 0 /* check for error */
- bne pputh_err
- pputh_skip:
- addic. r30, r30, -1
- bne pputh_nxt
- xor r3, r3, r3 /* Clear error code */
- b pputh_done
- pputh_err:
- addi r3, 0, -1 /* set error code */
- pputh_done:
- /* restore stack and return */
- lmw r30, 8(r1) /* restore r30 - r31 from stack */
- lwz r0, +20(r1) /* Get saved link register */
- addi r1, r1, +16 /* Remove frame from stack */
- mtlr r0 /* Restore link register */
- blr /* Return to calling function */
|