2
* Copyright (c) 2007 Michal Kebrt, Petr Stepan
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
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.
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.
29
/** @addtogroup arm32gxemul
33
* @brief GXemul drivers.
36
#include <arch/exception.h>
37
#include <arch/mach/testarm/testarm.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>
46
#include <ddi/device.h>
48
#include <sysinfo/sysinfo.h>
49
#include <interrupt.h>
56
static irq_t gxemul_timer_irq;
58
struct arm_machine_ops machine_ops = {
62
gxemul_timer_irq_start,
64
gxemul_get_memory_size,
67
gxemul_get_fb_address,
73
void gxemul_init(void)
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);
80
void gxemul_fb_init(void)
82
fb_properties_t prop = {
83
.addr = GXEMUL_FB_ADDRESS,
88
.visual = VISUAL_RGB_8_8_8,
93
void gxemul_output_init(void)
95
dsrlnout_init((ioport8_t *) gxemul_kbd);
98
void gxemul_input_init(void)
100
#ifdef CONFIG_ARM_KBD
102
* Initialize the GXemul keyboard port. Then initialize the serial line
103
* module and connect it to the GXemul keyboard.
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();
110
indev_t *sink = stdin_wire();
111
indev_t *srln = srln_wire(srln_instance, sink);
112
dsrlnin_wire(dsrlnin_instance, srln);
117
* This is the necessary evil until the userspace driver is entirely
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);
126
/** Starts gxemul Real Time Clock device, which asserts regular interrupts.
128
* @param frequency Interrupts frequency (0 disables RTC).
130
static void gxemul_timer_start(uint32_t frequency)
132
*((uint32_t *) (gxemul_rtc + GXEMUL_RTC_FREQ_OFFSET))
136
static irq_ownership_t gxemul_timer_claim(irq_t *irq)
141
/** Timer interrupt handler.
143
* @param irq Interrupt information.
144
* @param arg Not used.
146
static void gxemul_timer_irq_handler(irq_t *irq)
149
* We are holding a lock which prevents preemption.
150
* Release the lock, call clock() and reacquire the lock again.
152
spinlock_unlock(&irq->lock);
154
spinlock_lock(&irq->lock);
156
/* acknowledge tick */
157
*((uint32_t *) (gxemul_rtc + GXEMUL_RTC_ACK_OFFSET))
161
/** Initializes and registers timer interrupt handler. */
162
static void gxemul_timer_irq_init(void)
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;
170
irq_register(&gxemul_timer_irq);
176
* Initiates regular timer interrupts after initializing
177
* corresponding interrupt handler.
179
void gxemul_timer_irq_start(void)
181
gxemul_timer_irq_init();
182
gxemul_timer_start(GXEMUL_TIMER_FREQ);
185
/** Returns the size of emulated memory.
187
* @return Size in bytes.
189
uintptr_t gxemul_get_memory_size(void)
191
return *((uintptr_t *) (GXEMUL_MP_ADDRESS + GXEMUL_MP_MEMSIZE_OFFSET));
195
/** Returns the mask of active interrupts. */
196
static inline uint32_t gxemul_irqc_get_sources(void)
198
return *((uint32_t *) gxemul_irqc);
201
/** Interrupt Exception handler.
203
* Determines the sources of interrupt and calls their handlers.
205
void gxemul_irq_exception(int exc_no, istate_t *istate)
207
uint32_t sources = gxemul_irqc_get_sources();
210
for (i = 0; i < GXEMUL_IRQC_MAX_IRQ; i++) {
211
if (sources & (1 << i)) {
212
irq_t *irq = irq_dispatch_and_lock(i);
214
/* The IRQ handler was found. */
216
spinlock_unlock(&irq->lock);
218
/* Spurious interrupt.*/
219
printf("cpu%d: spurious interrupt (inum=%d)\n",
226
void gxemul_cpu_halt(void)
228
*((char *) (gxemul_kbd + GXEMUL_HALT_OFFSET)) = 0;
231
void gxemul_frame_init(void)
235
uintptr_t gxemul_get_fb_address()
237
return ((uintptr_t)GXEMUL_FB_ADDRESS);