Subversion Repositories HelenOS

Rev

Rev 4669 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (c) 2007 Michal Kebrt, Petr Stepan
  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 arm32gxemul
  30.  * @{
  31.  */
  32. /** @file
  33.  *  @brief GXemul drivers.
  34.  */
  35.  
  36. #include <arch/exception.h>
  37. #include <arch/mach/testarm/testarm.h>
  38. #include <mm/page.h>
  39. #include <genarch/fb/fb.h>
  40. #include <genarch/fb/visuals.h>
  41. #include <genarch/drivers/dsrln/dsrlnin.h>
  42. #include <genarch/drivers/dsrln/dsrlnout.h>
  43. #include <genarch/srln/srln.h>
  44. #include <console/console.h>
  45. #include <ddi/irq.h>
  46. #include <ddi/device.h>
  47. #include <config.h>
  48. #include <sysinfo/sysinfo.h>
  49. #include <interrupt.h>
  50. #include <print.h>
  51.  
  52.  
  53. void *gxemul_kbd;
  54. void *gxemul_rtc;
  55. void *gxemul_irqc;
  56. static irq_t gxemul_timer_irq;
  57.  
  58. struct arm_machine_ops machine_ops = {
  59.     MACHINE_GENFUNC,
  60.     MACHINE_GENFUNC,
  61.     gxemul_init,
  62.     gxemul_timer_irq_start,
  63.     gxemul_cpu_halt,
  64.     gxemul_get_memory_size,
  65.     gxemul_fb_init,
  66.     gxemul_irq_exception,
  67.     gxemul_get_fb_address,
  68.     gxemul_frame_init,
  69.     gxemul_output_init,
  70.     gxemul_input_init
  71. };
  72.  
  73. void gxemul_init(void)
  74. {
  75.     gxemul_kbd = (void *) hw_map(GXEMUL_KBD_ADDRESS, PAGE_SIZE);
  76.     gxemul_rtc = (void *) hw_map(GXEMUL_RTC_ADDRESS, PAGE_SIZE);
  77.     gxemul_irqc = (void *) hw_map(GXEMUL_IRQC_ADDRESS, PAGE_SIZE);
  78. }
  79.  
  80. void gxemul_fb_init(void)
  81. {
  82.     fb_properties_t prop = {
  83.         .addr = GXEMUL_FB_ADDRESS,
  84.         .offset = 0,
  85.         .x = 640,
  86.         .y = 480,
  87.         .scan = 1920,
  88.         .visual = VISUAL_RGB_8_8_8,
  89.     };
  90.     fb_init(&prop);
  91. }
  92.  
  93. void gxemul_output_init(void)
  94. {
  95.     dsrlnout_init((ioport8_t *) gxemul_kbd);
  96. }
  97.  
  98. void gxemul_input_init(void)
  99. {
  100. #ifdef CONFIG_ARM_KBD
  101.     /*
  102.      * Initialize the GXemul keyboard port. Then initialize the serial line
  103.      * module and connect it to the GXemul keyboard.
  104.      */
  105.     dsrlnin_instance_t *dsrlnin_instance
  106.         = dsrlnin_init((dsrlnin_t *) gxemul_kbd, GXEMUL_KBD_IRQ);
  107.     if (dsrlnin_instance) {
  108.         srln_instance_t *srln_instance = srln_init();
  109.         if (srln_instance) {
  110.             indev_t *sink = stdin_wire();
  111.             indev_t *srln = srln_wire(srln_instance, sink);
  112.             dsrlnin_wire(dsrlnin_instance, srln);
  113.         }
  114.     }
  115.  
  116.     /*
  117.      * This is the necessary evil until the userspace driver is entirely
  118.      * self-sufficient.
  119.      */
  120.     sysinfo_set_item_val("kbd", NULL, true);
  121.     sysinfo_set_item_val("kbd.inr", NULL, GXEMUL_KBD_IRQ);
  122.     sysinfo_set_item_val("kbd.address.virtual", NULL, (unative_t) gxemul_kbd);
  123. #endif
  124. }
  125.  
  126. /** Starts gxemul Real Time Clock device, which asserts regular interrupts.
  127.  *
  128.  * @param frequency Interrupts frequency (0 disables RTC).
  129.  */
  130. static void gxemul_timer_start(uint32_t frequency)
  131. {
  132.     *((uint32_t *) (gxemul_rtc + GXEMUL_RTC_FREQ_OFFSET))
  133.         = frequency;
  134. }
  135.  
  136. static irq_ownership_t gxemul_timer_claim(irq_t *irq)
  137. {
  138.     return IRQ_ACCEPT;
  139. }
  140.  
  141. /** Timer interrupt handler.
  142.  *
  143.  * @param irq Interrupt information.
  144.  * @param arg Not used.
  145.  */
  146. static void gxemul_timer_irq_handler(irq_t *irq)
  147. {
  148.     /*
  149.     * We are holding a lock which prevents preemption.
  150.     * Release the lock, call clock() and reacquire the lock again.
  151.     */
  152.     spinlock_unlock(&irq->lock);
  153.     clock();
  154.     spinlock_lock(&irq->lock);
  155.  
  156.     /* acknowledge tick */
  157.     *((uint32_t *) (gxemul_rtc + GXEMUL_RTC_ACK_OFFSET))
  158.         = 0;
  159. }
  160.  
  161. /** Initializes and registers timer interrupt handler. */
  162. static void gxemul_timer_irq_init(void)
  163. {
  164.         irq_initialize(&gxemul_timer_irq);
  165.         gxemul_timer_irq.devno = device_assign_devno();
  166.         gxemul_timer_irq.inr = GXEMUL_TIMER_IRQ;
  167.         gxemul_timer_irq.claim = gxemul_timer_claim;
  168.         gxemul_timer_irq.handler = gxemul_timer_irq_handler;
  169.  
  170.         irq_register(&gxemul_timer_irq);
  171. }
  172.  
  173.  
  174. /** Starts timer.
  175.  *
  176.  * Initiates regular timer interrupts after initializing
  177.  * corresponding interrupt handler.
  178.  */
  179. void gxemul_timer_irq_start(void)
  180. {
  181.         gxemul_timer_irq_init();
  182.         gxemul_timer_start(GXEMUL_TIMER_FREQ);
  183. }
  184.  
  185. /** Returns the size of emulated memory.
  186.  *
  187.  * @return Size in bytes.
  188.  */
  189. uintptr_t gxemul_get_memory_size(void)
  190. {
  191.         return  *((uintptr_t *) (GXEMUL_MP_ADDRESS + GXEMUL_MP_MEMSIZE_OFFSET));
  192. }
  193.  
  194.  
  195. /** Returns the mask of active interrupts. */
  196. static inline uint32_t gxemul_irqc_get_sources(void)
  197. {
  198.     return *((uint32_t *) gxemul_irqc);
  199. }
  200.  
  201. /** Interrupt Exception handler.
  202.  *
  203.  * Determines the sources of interrupt and calls their handlers.
  204.  */
  205. void gxemul_irq_exception(int exc_no, istate_t *istate)
  206. {
  207.     uint32_t sources = gxemul_irqc_get_sources();
  208.     unsigned int i;
  209.  
  210.     for (i = 0; i < GXEMUL_IRQC_MAX_IRQ; i++) {
  211.         if (sources & (1 << i)) {
  212.             irq_t *irq = irq_dispatch_and_lock(i);
  213.             if (irq) {
  214.                 /* The IRQ handler was found. */
  215.                 irq->handler(irq);
  216.                 spinlock_unlock(&irq->lock);
  217.             } else {
  218.                 /* Spurious interrupt.*/
  219.                 printf("cpu%d: spurious interrupt (inum=%d)\n",
  220.                     CPU->id, i);
  221.             }
  222.         }
  223.     }
  224. }
  225.  
  226. void gxemul_cpu_halt(void)
  227. {
  228.     *((char *) (gxemul_kbd + GXEMUL_HALT_OFFSET)) = 0;
  229. }
  230.  
  231. void gxemul_frame_init(void)
  232. {
  233. }
  234.  
  235. uintptr_t gxemul_get_fb_address()
  236. {
  237.     return ((uintptr_t)GXEMUL_FB_ADDRESS);
  238. }
  239.  
  240.  
  241. /** @}
  242.  */
  243.