Rev 2340 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 2340 | Rev 2355 | ||
---|---|---|---|
Line 43... | Line 43... | ||
43 | #include <mm/page.h> |
43 | #include <mm/page.h> |
44 | #include <arch/machine.h> |
44 | #include <arch/machine.h> |
45 | #include <arch/debug/print.h> |
45 | #include <arch/debug/print.h> |
46 | 46 | ||
47 | 47 | ||
48 | /** Address of devices. */ |
48 | /** Addresses of devices. */ |
49 | #define GXEMUL_VIDEORAM 0x10000000 |
49 | #define GXEMUL_VIDEORAM 0x10000000 |
50 | #define GXEMUL_KBD 0x10000000 |
50 | #define GXEMUL_KBD 0x10000000 |
51 | #define GXEMUL_HALT_OFFSET 0x10 |
51 | #define GXEMUL_HALT_OFFSET 0x10 |
52 | #define GXEMUL_RTC 0x15000000 |
52 | #define GXEMUL_RTC 0x15000000 |
53 | #define GXEMUL_RTC_FREQ_OFFSET 0x100 |
53 | #define GXEMUL_RTC_FREQ_OFFSET 0x100 |
Line 81... | Line 81... | ||
81 | .suspend = gxemul_disable, |
81 | .suspend = gxemul_disable, |
82 | .write = gxemul_write, |
82 | .write = gxemul_write, |
83 | .read = gxemul_do_read, |
83 | .read = gxemul_do_read, |
84 | }; |
84 | }; |
85 | 85 | ||
86 | /** Return the mask of active interrupts. */ |
86 | /** Returns the mask of active interrupts. */ |
87 | static inline uint32_t gxemul_irqc_get_sources(void) |
87 | static inline uint32_t gxemul_irqc_get_sources(void) |
88 | { |
88 | { |
89 | return *(uint32_t*) gxemul_hw_map.irqc; |
89 | return *(uint32_t*) gxemul_hw_map.irqc; |
90 | } |
90 | } |
91 | 91 | ||
Line 236... | Line 236... | ||
236 | static irq_ownership_t gxemul_timer_claim(void) |
236 | static irq_ownership_t gxemul_timer_claim(void) |
237 | { |
237 | { |
238 | return IRQ_ACCEPT; |
238 | return IRQ_ACCEPT; |
239 | } |
239 | } |
240 | 240 | ||
- | 241 | /** Timer interrupt handler. |
|
- | 242 | * |
|
- | 243 | * @param irq interrupt information |
|
- | 244 | */ |
|
241 | static void gxemul_timer_irq_handler(irq_t *irq, void *arg, ...) |
245 | static void gxemul_timer_irq_handler(irq_t *irq, void *arg, ...) |
242 | { |
246 | { |
243 | /* TODO time drifts ?? |
247 | /* TODO time drifts ?? |
244 | unsigned long drift; |
248 | unsigned long drift; |
245 | 249 | ||
Line 267... | Line 271... | ||
267 | if (virtual_timer_fnc != NULL) |
271 | if (virtual_timer_fnc != NULL) |
268 | virtual_timer_fnc(); |
272 | virtual_timer_fnc(); |
269 | */ |
273 | */ |
270 | } |
274 | } |
271 | 275 | ||
272 | /** |
- | |
273 | * Initializes and registers timer interrupt handler. |
276 | /** Initializes and registers timer interrupt handler. |
274 | */ |
277 | */ |
275 | static void gxemul_timer_irq_init() |
278 | static void gxemul_timer_irq_init() |
276 | { |
279 | { |
277 | irq_initialize(&gxemul_timer_irq); |
280 | irq_initialize(&gxemul_timer_irq); |
278 | gxemul_timer_irq.devno = device_assign_devno(); |
281 | gxemul_timer_irq.devno = device_assign_devno(); |
Line 281... | Line 284... | ||
281 | gxemul_timer_irq.handler = gxemul_timer_irq_handler; |
284 | gxemul_timer_irq.handler = gxemul_timer_irq_handler; |
282 | 285 | ||
283 | irq_register(&gxemul_timer_irq); |
286 | irq_register(&gxemul_timer_irq); |
284 | } |
287 | } |
285 | 288 | ||
- | 289 | /** Starts timer. |
|
- | 290 | * |
|
- | 291 | * Initiates regular timer interrupts after initializing |
|
- | 292 | * corresponding interrupt handler. |
|
- | 293 | */ |
|
286 | void machine_timer_irq_start() |
294 | void machine_timer_irq_start() |
287 | { |
295 | { |
288 | gxemul_timer_irq_init(); |
296 | gxemul_timer_irq_init(); |
289 | gxemul_timer_start(GXEMUL_TIMER_FREQ); |
297 | gxemul_timer_start(GXEMUL_TIMER_FREQ); |
290 | } |
298 | } |
291 | 299 | ||
- | 300 | /** Returns the size of emulated memory. |
|
- | 301 | * |
|
- | 302 | * @return size in bytes |
|
- | 303 | */ |
|
292 | size_t machine_get_memory_size(void) |
304 | size_t machine_get_memory_size(void) |
293 | { |
305 | { |
294 | return *((int*)(GXEMUL_MP + GXEMUL_MP_MEMSIZE_OFFSET)); |
306 | return *((int*)(GXEMUL_MP + GXEMUL_MP_MEMSIZE_OFFSET)); |
295 | } |
307 | } |
296 | 308 | ||
Line 304... | Line 316... | ||
304 | } |
316 | } |
305 | 317 | ||
306 | *(addr) = ch; |
318 | *(addr) = ch; |
307 | } |
319 | } |
308 | 320 | ||
- | 321 | /** Stops gxemul. */ |
|
309 | void machine_cpu_halt(void) |
322 | void machine_cpu_halt(void) |
310 | { |
323 | { |
311 | char * addr = 0; |
324 | char * addr = 0; |
312 | if (!hw_map_init_called) { |
325 | if (!hw_map_init_called) { |
313 | addr = (char *) GXEMUL_KBD; |
326 | addr = (char *) GXEMUL_KBD; |
Line 316... | Line 329... | ||
316 | } |
329 | } |
317 | 330 | ||
318 | *(addr + GXEMUL_HALT_OFFSET) = '\0'; |
331 | *(addr + GXEMUL_HALT_OFFSET) = '\0'; |
319 | } |
332 | } |
320 | 333 | ||
- | 334 | /** Gxemul specific interrupt exception handler. |
|
- | 335 | * |
|
- | 336 | * Determines sources of the interrupt from interrupt controller and |
|
- | 337 | * calls high-level handlers for them. |
|
- | 338 | * |
|
- | 339 | * @param exc_no interrupt exception number |
|
- | 340 | * @param istate saved processor state |
|
- | 341 | */ |
|
321 | void machine_irq_exception(int exc_no, istate_t *istate) |
342 | void machine_irq_exception(int exc_no, istate_t *istate) |
322 | { |
343 | { |
323 | /* switch to Undefined mode */ |
- | |
324 | /* |
- | |
325 | asm volatile( |
- | |
326 | "stmfd sp!, {r0-r3}\n" |
- | |
327 | "mov r1, sp\n" |
- | |
328 | "mov r2, lr\n" |
- | |
329 | "mrs r3, spsr\n" |
- | |
330 | "mrs r0, cpsr\n" |
- | |
331 | "bic r0, r0, #0x1f\n" |
- | |
332 | "orr r0, r0, #0x1b\n" |
- | |
333 | "msr cpsr_c, r0\n" |
- | |
334 | "mov sp, r1\n" |
- | |
335 | "mov lr, r2\n" |
- | |
336 | "msr spsr, r3\n" |
- | |
337 | "ldmfd sp!, {r0-r3}\n" |
- | |
338 | ); |
- | |
339 | */ |
- | |
340 | - | ||
341 | uint32_t sources = gxemul_irqc_get_sources(); |
344 | uint32_t sources = gxemul_irqc_get_sources(); |
342 | int i = 0; |
345 | int i = 0; |
343 | for (; i < GXEMUL_IRQC_MAX_IRQ; i++) { |
346 | for (; i < GXEMUL_IRQC_MAX_IRQ; i++) { |
344 | if (sources & (1 << i)) { |
347 | if (sources & (1 << i)) { |
345 | irq_t *irq = irq_dispatch_and_lock(i); |
348 | irq_t *irq = irq_dispatch_and_lock(i); |
Line 351... | Line 354... | ||
351 | /* Spurious interrupt.*/ |
354 | /* Spurious interrupt.*/ |
352 | dprintf("cpu%d: spurious interrupt (inum=%d)\n", CPU->id, i); |
355 | dprintf("cpu%d: spurious interrupt (inum=%d)\n", CPU->id, i); |
353 | } |
356 | } |
354 | } |
357 | } |
355 | } |
358 | } |
356 | /* TODO remove after testing the above code |
- | |
357 | noirq = 0; |
- | |
358 | if (i == CONSOLE_IRQ) { |
- | |
359 | char readchar = *(char*)0x10000000; |
- | |
360 | if (readchar == 0) { |
- | |
361 | aux_puts("?"); |
- | |
362 | } |
- | |
363 | else { |
- | |
364 | dprintf("%c", readchar); |
- | |
365 | } |
- | |
366 | |
- | |
367 | } |
- | |
368 | else if (i == TIMER_IRQ) { |
- | |
369 | dprintf("\n.\n"); |
- | |
370 | //acknowledge |
- | |
371 | *(uint32_t*)0x15000110 = 0; |
- | |
372 | } |
- | |
373 | } |
- | |
374 | } |
- | |
375 | - | ||
376 | if (noirq) |
- | |
377 | aux_puts("IRQ exception without source\n");*/ |
- | |
378 | } |
359 | } |
379 | 360 | ||
380 | 361 | ||
381 | /** @} |
362 | /** @} |
382 | */ |
363 | */ |