Subversion Repositories HelenOS

Rev

Rev 3549 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (c) 2008 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   SGCN driver.
  35.  */
  36.  
  37. #include <arch/drivers/sgcn.h>
  38. #include <genarch/ofw/ofw_tree.h>
  39. #include <debug.h>
  40. #include <func.h>
  41. #include <print.h>
  42. #include <mm/page.h>
  43. #include <console/chardev.h>
  44. #include <console/console.h>
  45. #include <synch/spinlock.h>
  46.  
  47. /*
  48.  * Physical address at which the SBBC starts. This value has been obtained
  49.  * by inspecting (using Simics) memory accesses made by OBP. It is valid
  50.  * for the Simics-simulated Serengeti machine. The author of this code is
  51.  * not sure whether this value is valid generally.
  52.  */
  53. #define SBBC_START      0x63000000000
  54.  
  55. /* offset of SRAM within the SBBC memory */
  56. #define SBBC_SRAM_OFFSET    0x900000
  57.  
  58. /* magic string contained at the beginning of SRAM */
  59. #define SRAM_TOC_MAGIC      "TOCSRAM"
  60.  
  61. /*
  62.  * Key into the SRAM table of contents which identifies the entry
  63.  * describing the OBP console buffer. It is worth mentioning
  64.  * that the OBP console buffer is not the only console buffer
  65.  * which can be used. It is, however, used because when the kernel
  66.  * is running, the OBP buffer is not used by OBP any more but OBP
  67.  * has already made neccessary arangements so that the output will
  68.  * be read from the OBP buffer and input will go to the OBP buffer.
  69.  * Therefore HelenOS needs to make no such arrangements any more.
  70.  */
  71. #define CONSOLE_KEY     "OBPCONS"
  72.  
  73. /* magic string contained at the beginning of the console buffer */
  74. #define SGCN_BUFFER_MAGIC   "CON"
  75.  
  76.  
  77. /*
  78.  * Returns a pointer to the object of a given type which is placed at the given
  79.  * offset from the SRAM beginning.
  80.  */
  81. #define SRAM(type, offset)  ((type *) (sram_begin + (offset)))
  82.  
  83. /* Returns a pointer to the SRAM table of contents. */
  84. #define SRAM_TOC        (SRAM(iosram_toc_t, 0))
  85.  
  86. /*
  87.  * Returns a pointer to the object of a given type which is placed at the given
  88.  * offset from the console buffer beginning.
  89.  */
  90. #define SGCN_BUFFER(type, offset) \
  91.                 ((type *) (sgcn_buffer_begin + (offset)))
  92.  
  93. /* Returns a pointer to the console buffer header. */
  94. #define SGCN_BUFFER_HEADER  (SGCN_BUFFER(sgcn_buffer_header_t, 0))
  95.  
  96.  
  97. /* starting address of SRAM, will be set by the init_sram_begin function */
  98. static uintptr_t sram_begin;
  99.  
  100. /*
  101.  * starting address of the SGCN buffer, will be set by the
  102.  * init_sgcn_buffer_begin function
  103.  */
  104. static uintptr_t sgcn_buffer_begin;
  105.  
  106.  
  107. /*
  108.  * Ensures that writing to the buffer and consequent update of the write pointer
  109.  * are together one atomic operation.
  110.  */
  111. SPINLOCK_INITIALIZE(sgcn_output_lock);
  112.  
  113.  
  114. static void sgcn_putchar(struct chardev * cd, const char c);
  115.  
  116. /** character device operations */
  117. static chardev_operations_t sgcn_ops = {
  118.     .suspend = NULL,
  119.     .resume = NULL,
  120.     .write = sgcn_putchar,
  121.     .read = NULL
  122. };
  123.  
  124. /** SGCN character device */
  125. chardev_t sgcn_stdout;
  126.  
  127. /**
  128.  * Initializes the starting address of SRAM.
  129.  *
  130.  * The SRAM starts 0x900000 + C bytes behind the SBBC start in the
  131.  * physical memory, where C is the value read from the "iosram-toc"
  132.  * property of the "/chosen" OBP node. The sram_begin variable will
  133.  * be set to the virtual address which maps to the SRAM physical
  134.  * address.
  135.  */
  136. static void init_sram_begin(void)
  137. {
  138.     ofw_tree_node_t *chosen;
  139.     ofw_tree_property_t *iosram_toc;
  140.  
  141.     chosen = ofw_tree_lookup("/chosen");
  142.     if (!chosen)
  143.         panic("Can't find /chosen.\n");
  144.  
  145.     iosram_toc = ofw_tree_getprop(chosen, "iosram-toc");
  146.     if (!iosram_toc)
  147.         panic("Can't find property \"iosram-toc\".\n");
  148.     if (!iosram_toc->value)
  149.         panic("Can't find SRAM TOC.\n");
  150.  
  151.     sram_begin = hw_map(
  152.         SBBC_START + SBBC_SRAM_OFFSET
  153.         + *((uint32_t *) iosram_toc->value),
  154.         128 * 1024);
  155. }
  156.  
  157. /**
  158.  * Initializes the starting address of the SGCN buffer.
  159.  *
  160.  * The offset of the SGCN buffer within SRAM is obtained from the
  161.  * SRAM table of contents. The table of contents contains
  162.  * information about several buffers, among which there is an OBP
  163.  * console buffer - this one will be used as the SGCN buffer.
  164.  */
  165. static void sgcn_buffer_begin_init(void)
  166. {
  167.     init_sram_begin();
  168.        
  169.     ASSERT(strcmp(SRAM_TOC->magic, SRAM_TOC_MAGIC) == 0);
  170.    
  171.     /* lookup TOC entry with the correct key */
  172.     uint32_t i;
  173.     for (i = 0; i < MAX_TOC_ENTRIES; i++) {
  174.         if (strcmp(SRAM_TOC->keys[i].key, CONSOLE_KEY) == 0)
  175.             break;
  176.     }
  177.     ASSERT(i < MAX_TOC_ENTRIES);
  178.    
  179.     sgcn_buffer_begin = sram_begin + SRAM_TOC->keys[i].offset;
  180. }
  181.  
  182. /**
  183.  * Writes a single character to the SGCN (circular) output buffer
  184.  * and updates the output write pointer so that SGCN gets to know
  185.  * that the character has been written.
  186.  */
  187. static void sgcn_do_putchar(const char c)
  188. {
  189.     uint32_t begin = SGCN_BUFFER_HEADER->out_begin;
  190.     uint32_t end = SGCN_BUFFER_HEADER->out_end;
  191.     uint32_t size = end - begin;
  192.    
  193.     /* we need pointers to volatile variables */
  194.     volatile char *buf_ptr = (volatile char *)
  195.         SGCN_BUFFER(char, SGCN_BUFFER_HEADER->out_wrptr);
  196.     volatile uint32_t *out_wrptr_ptr = &(SGCN_BUFFER_HEADER->out_wrptr);
  197.     volatile uint32_t *out_rdptr_ptr = &(SGCN_BUFFER_HEADER->out_rdptr);
  198.  
  199.     /*
  200.      * Write the character and increment the write pointer modulo the
  201.      * output buffer size. Note that if we are to rewrite a character
  202.      * which has not been read by the SGCN controller yet (i.e. the output
  203.      * buffer is full), we need to wait until the controller reads some more
  204.      * characters. We wait actively, which means that all threads waiting
  205.      * for the lock are blocked. However, this situation is
  206.      *   1) rare - the output buffer is big, so filling the whole
  207.      *             output buffer is improbable
  208.      *   2) short-lasting - it will take the controller only a fraction
  209.      *             of millisecond to pick the unread characters up
  210.      *   3) not serious - the blocked threads are those that print something
  211.      *             to user console, which is not a time-critical operation
  212.      */
  213.     uint32_t new_wrptr = (((*out_wrptr_ptr) - begin + 1) % size) + begin;
  214.     while (*out_rdptr_ptr == new_wrptr)
  215.         ;
  216.     *buf_ptr = c;
  217.     *out_wrptr_ptr = new_wrptr;
  218. }
  219.  
  220. /**
  221.  * SGCN output operation. Prints a single character to the SGCN. If the line
  222.  * feed character is written ('\n'), the carriage return character ('\r') is
  223.  * written straight away.
  224.  */
  225. static void sgcn_putchar(struct chardev * cd, const char c)
  226. {
  227.     spinlock_lock(&sgcn_output_lock);
  228.    
  229.     sgcn_do_putchar(c);
  230.     if (c == '\n') {
  231.         sgcn_do_putchar('\r');
  232.     }
  233.    
  234.     spinlock_unlock(&sgcn_output_lock);
  235. }
  236.  
  237. /**
  238.  * A public function which initializes I/O from/to Serengeti console
  239.  * and sets it as a default input/output.
  240.  */
  241. void sgcn_init(void)
  242. {
  243.     sgcn_buffer_begin_init();
  244.    
  245.     chardev_initialize("sgcn_output", &sgcn_stdout, &sgcn_ops);
  246.     stdout = &sgcn_stdout;
  247.    
  248.    
  249.     printf("SGCN buffer begin = %d, in read ptr = %" PRIu32 ".", sgcn_buffer_begin, SGCN_BUFFER_HEADER->in_wrptr);
  250. }
  251.  
  252. /** @}
  253.  */