83,6 → 83,7 |
.read = gxemul_do_read, |
}; |
|
|
/** Returns the mask of active interrupts. */ |
static inline uint32_t gxemul_irqc_get_sources(void) |
{ |
89,6 → 90,7 |
return *(uint32_t*) gxemul_hw_map.irqc; |
} |
|
|
/** Masks interrupt. |
* |
* @param irq interrupt number |
98,6 → 100,7 |
*(uint32_t*) gxemul_hw_map.irqc_mask = irq; |
} |
|
|
/** Unmasks interrupt. |
* |
* @param irq interrupt number |
107,6 → 110,7 |
*(uint32_t*) gxemul_hw_map.irqc_unmask = irq; |
} |
|
|
/** Initializes #gxemul_hw_map. */ |
void machine_hw_map_init(void) |
{ |
114,6 → 118,7 |
gxemul_hw_map.kbd = hw_map(GXEMUL_KBD, PAGE_SIZE); |
gxemul_hw_map.rtc = hw_map(GXEMUL_RTC, PAGE_SIZE); |
gxemul_hw_map.irqc = hw_map(GXEMUL_IRQC, PAGE_SIZE); |
gxemul_hw_map.fb = hw_map(GXEMUL_FB, PAGE_SIZE); |
|
gxemul_hw_map.rtc_freq = gxemul_hw_map.rtc + GXEMUL_RTC_FREQ_OFFSET; |
gxemul_hw_map.rtc_ack = gxemul_hw_map.rtc + GXEMUL_RTC_ACK_OFFSET; |
123,6 → 128,7 |
hw_map_init_called = true; |
} |
|
|
/** Putchar that works with gxemul */ |
static void gxemul_write(chardev_t *dev, const char ch) |
{ |
129,6 → 135,7 |
*((char *) gxemul_hw_map.videoram) = ch; |
} |
|
|
/* Called from getc(). */ |
static void gxemul_enable(chardev_t *dev) |
{ |
135,6 → 142,7 |
gxemul_irqc_unmask(GXEMUL_KBD_IRQ); |
} |
|
|
/* Called from getc(). */ |
static void gxemul_disable(chardev_t *dev) |
{ |
141,7 → 149,11 |
gxemul_irqc_mask(GXEMUL_KBD_IRQ); |
} |
|
/** Read character using polling, assume interrupts disabled */ |
|
/** Read character using polling, assume interrupts disabled. |
* |
* @param dev Not used. |
*/ |
static char gxemul_do_read(chardev_t *dev) |
{ |
char ch; |
158,28 → 170,33 |
} |
} |
|
|
/** Process keyboard interrupt. */ |
static void gxemul_irq_handler(irq_t *irq, void *arg, ...) |
{ |
if ((irq->notif_cfg.notify) && (irq->notif_cfg.answerbox)) |
if ((irq->notif_cfg.notify) && (irq->notif_cfg.answerbox)) { |
ipc_irq_send_notif(irq); |
else { |
} else { |
char ch = 0; |
|
ch = *((char *) gxemul_hw_map.kbd); |
if (ch =='\r') |
ch = '\n'; |
if (ch == 0x7f) |
ch = '\b'; |
chardev_push_character(&console, ch); |
ch = *((char *) gxemul_hw_map.kbd); |
if (ch == '\r') { |
ch = '\n'; |
} |
if (ch == 0x7f) { |
ch = '\b'; |
} |
chardev_push_character(&console, ch); |
} |
} |
|
|
static irq_ownership_t gxemul_claim(void) |
{ |
return IRQ_ACCEPT; |
} |
|
|
void machine_grab_console(void) |
{ |
ipl_t ipl = interrupts_disable(); |
189,18 → 206,23 |
interrupts_restore(ipl); |
} |
|
|
void machine_release_console(void) |
{ |
ipl_t ipl = interrupts_disable(); |
spinlock_lock(&gxemul_irq.lock); |
if (gxemul_irq.notif_cfg.answerbox) |
if (gxemul_irq.notif_cfg.answerbox) { |
gxemul_irq.notif_cfg.notify = true; |
} |
spinlock_unlock(&gxemul_irq.lock); |
interrupts_restore(ipl); |
} |
|
|
/** Return console object representing gxemul console */ |
/** Initializes console object representing gxemul console. |
* |
* @param Console device number. |
*/ |
void machine_console_init(devno_t devno) |
{ |
chardev_initialize("gxemul_console", &console, &gxemul_ops); |
226,7 → 248,7 |
|
/** Starts gxemul Real Time Clock device, which asserts regular interrupts. |
* |
* @param frequency interrupts frequency (0 disables RTC) |
* @param frequency Interrupts frequency (0 disables RTC). |
*/ |
static void gxemul_timer_start(uint32_t frequency) |
{ |
233,14 → 255,17 |
*(uint32_t*) gxemul_hw_map.rtc_freq = frequency; |
} |
|
|
static irq_ownership_t gxemul_timer_claim(void) |
{ |
return IRQ_ACCEPT; |
} |
|
|
/** Timer interrupt handler. |
* |
* @param irq interrupt information |
* @param irq Interrupt information. |
* @param arg Not used. |
*/ |
static void gxemul_timer_irq_handler(irq_t *irq, void *arg, ...) |
{ |
273,8 → 298,8 |
*/ |
} |
|
/** Initializes and registers timer interrupt handler. |
*/ |
|
/** Initializes and registers timer interrupt handler. */ |
static void gxemul_timer_irq_init() |
{ |
irq_initialize(&gxemul_timer_irq); |
286,6 → 311,7 |
irq_register(&gxemul_timer_irq); |
} |
|
|
/** Starts timer. |
* |
* Initiates regular timer interrupts after initializing |
297,9 → 323,10 |
gxemul_timer_start(GXEMUL_TIMER_FREQ); |
} |
|
|
/** Returns the size of emulated memory. |
* |
* @return size in bytes |
* @return Size in bytes. |
*/ |
size_t machine_get_memory_size(void) |
{ |
306,6 → 333,7 |
return *((int*)(GXEMUL_MP + GXEMUL_MP_MEMSIZE_OFFSET)); |
} |
|
|
void machine_debug_putc(char ch) |
{ |
char * addr = 0; |
318,6 → 346,7 |
*(addr) = ch; |
} |
|
|
/** Stops gxemul. */ |
void machine_cpu_halt(void) |
{ |
331,13 → 360,14 |
*(addr + GXEMUL_HALT_OFFSET) = '\0'; |
} |
|
|
/** Gxemul specific interrupt exception handler. |
* |
* Determines sources of the interrupt from interrupt controller and |
* calls high-level handlers for them. |
* |
* @param exc_no interrupt exception number |
* @param istate saved processor state |
* @param exc_no Interrupt exception number. |
* @param istate Saved processor state. |
*/ |
void machine_irq_exception(int exc_no, istate_t *istate) |
{ |
359,5 → 389,10 |
} |
|
|
uintptr_t machine_get_fb_address(void) |
{ |
return gxemul_hw_map.fb; |
} |
|
/** @} |
*/ |