Subversion Repositories HelenOS

Rev

Rev 3467 | Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (c) 2006 Pavel Rimsky
  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. /** @addtogroup sparc64
  30.  * @{
  31.  */
  32. /**
  33.  * @file
  34.  * @brief Routines for writing characters directly to Simics CLI.
  35.  *
  36.  */
  37.  
  38. #include <console/chardev.h>
  39. #include <console/console.h>
  40. #include <synch/spinlock.h>
  41. #include <arch/drivers/simics_output.h>
  42.  
  43. /** maximum number of characters stored before printed */
  44. #define BUFSIZE 512
  45.  
  46. /* %g2 will store a magic value used during initialization */
  47. asm (".register %g2, #scratch");
  48.  
  49. /* %g3 will store the address (to be passed to Simics) of the buffer */
  50. asm (".register %g3, #scratch");
  51.  
  52. /* lock protecting the character buffer */
  53. SPINLOCK_INITIALIZE(simics_buf_lock);
  54.  
  55. static void simics_putchar(struct chardev * cd, char c);
  56.  
  57. /** character device operations - only writing will be supported */
  58. static chardev_operations_t simics_stdout_ops = {
  59.     .suspend = NULL,
  60.     .resume = NULL,
  61.     .write = simics_putchar,
  62.     .read = NULL
  63. };
  64.  
  65. /** Simics character device */
  66. chardev_t simics_stdout;
  67.  
  68. /**
  69.  * buffer to which output characters are stored before they're printed by Simics
  70.  */
  71. static volatile char buffer[BUFSIZE];
  72.  
  73. /** Writes a single character to the Simics CLI.
  74.  *
  75.  * The character is not written immediately, but it is stored to the first free
  76.  * position in the buffer, waiting for Simics' Python routine to read it
  77.  * and print it.
  78.  */
  79. static void simics_putchar(struct chardev * cd, char c)
  80. {
  81.     /* the first free position in the buffer */
  82.     static uint16_t current = 0;
  83.  
  84.     /* '\0' terminates a contiguous block of characters to be printed! */
  85.     if (c == '\0')
  86.         return;
  87.  
  88.     /* wait till buffer is non-full and other processors aren't writing to it */
  89.     while (1) {
  90.         while (buffer[current] != 0)
  91.             ;
  92.         if (spinlock_trylock(&simics_buf_lock))
  93.             break;
  94.     }
  95.  
  96.     buffer[current] = c;
  97.    
  98.     current = (current + 1) % BUFSIZE;
  99.     membar();
  100.    
  101.     spinlock_unlock(&simics_buf_lock);
  102. }
  103.  
  104. /** Initializes the Simics output.
  105.  *
  106.  * Passes the address of the buffer to the Simics' Python script and
  107.  * redirects kernel output to the Simics CLI.
  108.  */
  109. void simics_output_init(void)
  110. {
  111.     /* all buffer positions are free at the beginning */
  112.     uint16_t i;
  113.     for (i = 0; i < BUFSIZE; i++) {
  114.         buffer[i] = '\0';
  115.     }
  116.  
  117.     /*
  118.      * pass the address of the buffer to the Simics' Python script
  119.      *   - write it to the %g3 register
  120.      *   - write the magic value to the %g2 register
  121.      *     (so that the script knows that the value in %g3 is valid)
  122.      *   - loop until the value is read
  123.      *     (the script notifies us by setting %g2 to 0)
  124.      */
  125.     asm volatile (
  126.         "or %0, 0, %%g3\n"
  127.        
  128.         "set 0x18273645, %%g2\n"
  129.        
  130.         "0: cmp %%g2, 0\n"
  131.         "bnz 0b\n"
  132.         "nop"
  133.         :: "r" (buffer)
  134.     );
  135.                
  136.     /* redirect kernel output */
  137.     chardev_initialize("simics_output", &simics_stdout, &simics_stdout_ops);
  138.     stdout = &simics_stdout;
  139. }
  140.  
  141. /** @}
  142.  */
  143.