Subversion Repositories HelenOS

Rev

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

  1. /*
  2.  * Copyright (c) 2005 Ondrej Palkovsky
  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 mips32
  30.  * @{
  31.  */
  32. /** @file
  33.  */
  34.  
  35. #include <interrupt.h>
  36. #include <arch/cp0.h>
  37. #include <ipc/irq.h>
  38. #include <arch/drivers/serial.h>
  39. #include <console/chardev.h>
  40. #include <console/console.h>
  41.  
  42. #define SERIAL_IRQ 2
  43.  
  44. static irq_t serial_irq;
  45. static chardev_t console;
  46. static serial_t sconf[SERIAL_MAX];
  47. static bool kb_enabled;
  48.  
  49. static void serial_write(chardev_t *d, const char ch, bool silent)
  50. {
  51.     if (!silent) {
  52.         serial_t *sd = (serial_t *)d->data;
  53.        
  54.         if (ch == '\n')
  55.             serial_write(d, '\r');
  56.        
  57.         /* Wait until transmit buffer empty */
  58.         while (!(SERIAL_READ_LSR(sd->port) & (1 << TRANSMIT_EMPTY_BIT)));
  59.         SERIAL_WRITE(sd->port, ch);
  60.     }
  61. }
  62.  
  63. static void serial_enable(chardev_t *d)
  64. {
  65.     kb_enabled = true;
  66. }
  67.  
  68. static void serial_disable(chardev_t *d)
  69. {
  70.     kb_enabled = false;
  71. }
  72.  
  73. int serial_init(void)
  74. {
  75.     int i = 0;
  76.     if (SERIAL_READ_LSR(SERIAL_COM1) == 0x60) {
  77.         sconf[i].port = SERIAL_COM1;
  78.         sconf[i].irq = SERIAL_COM1_IRQ;
  79.         /* Enable interrupt on available data */
  80.         i++;
  81.     }
  82.     return i;
  83. }
  84.  
  85. /** Read character from serial port, wait until available */
  86. static char serial_do_read(chardev_t *dev)
  87. {
  88.     serial_t *sd = (serial_t *)dev->data;
  89.     char ch;
  90.  
  91.     while (!(SERIAL_READ_LSR(sd->port) & 1))
  92.         ;
  93.     ch = SERIAL_READ(sd->port);
  94.  
  95.     if (ch =='\r')
  96.         ch = '\n';
  97.     return ch;
  98. }
  99.  
  100. static void serial_handler(void)
  101. {
  102.     serial_t *sd = (serial_t *) console.data;
  103.     char ch;
  104.  
  105.     if (!(SERIAL_READ_LSR(sd->port) & 1))
  106.         return;
  107.     ch = SERIAL_READ(sd->port);
  108.  
  109.     if (ch =='\r')
  110.         ch = '\n';
  111.     chardev_push_character(&console, ch);
  112. }
  113.  
  114. /** Process keyboard interrupt. Does not work in simics? */
  115. static void serial_irq_handler(irq_t *irq, void *arg, ...)
  116. {
  117.     if ((irq->notif_cfg.notify) && (irq->notif_cfg.answerbox))
  118.         ipc_irq_send_notif(irq);
  119.     else
  120.         serial_handler();
  121. }
  122.  
  123. static irq_ownership_t serial_claim(void)
  124. {
  125.     return IRQ_ACCEPT;
  126. }
  127.  
  128. static chardev_operations_t serial_ops = {
  129.     .resume = serial_enable,
  130.     .suspend = serial_disable,
  131.     .write = serial_write,
  132.     .read = serial_do_read
  133. };
  134.  
  135. void serial_console(devno_t devno)
  136. {
  137.     serial_t *sd = &sconf[0];
  138.    
  139.     chardev_initialize("serial_console", &console, &serial_ops);
  140.     console.data = sd;
  141.     kb_enabled = true;
  142.    
  143.     irq_initialize(&serial_irq);
  144.     serial_irq.devno = devno;
  145.     serial_irq.inr = SERIAL_IRQ;
  146.     serial_irq.claim = serial_claim;
  147.     serial_irq.handler = serial_irq_handler;
  148.     irq_register(&serial_irq);
  149.    
  150.     /* I don't know why, but the serial interrupts simply
  151.        don't work on simics */
  152.     virtual_timer_fnc = &serial_handler;
  153.    
  154.     stdin = &console;
  155.     stdout = &console;
  156. }
  157.  
  158. /** @}
  159.  */
  160.