Rev 3022 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 3022 | Rev 4055 | ||
---|---|---|---|
Line 32... | Line 32... | ||
32 | /** @file |
32 | /** @file |
33 | * @brief GXemul drivers. |
33 | * @brief GXemul drivers. |
34 | */ |
34 | */ |
35 | 35 | ||
36 | #include <interrupt.h> |
36 | #include <interrupt.h> |
37 | #include <ipc/irq.h> |
- | |
38 | #include <console/chardev.h> |
37 | #include <console/chardev.h> |
39 | #include <arch/drivers/gxemul.h> |
38 | #include <arch/drivers/gxemul.h> |
40 | #include <console/console.h> |
39 | #include <console/console.h> |
41 | #include <sysinfo/sysinfo.h> |
40 | #include <sysinfo/sysinfo.h> |
42 | #include <print.h> |
41 | #include <print.h> |
Line 70... | Line 69... | ||
70 | 69 | ||
71 | static bool hw_map_init_called = false; |
70 | static bool hw_map_init_called = false; |
72 | 71 | ||
73 | static void gxemul_kbd_enable(chardev_t *dev); |
72 | static void gxemul_kbd_enable(chardev_t *dev); |
74 | static void gxemul_kbd_disable(chardev_t *dev); |
73 | static void gxemul_kbd_disable(chardev_t *dev); |
75 | static void gxemul_write(chardev_t *dev, const char ch); |
74 | static void gxemul_write(chardev_t *dev, const char ch, bool silent); |
76 | static char gxemul_do_read(chardev_t *dev); |
75 | static char gxemul_do_read(chardev_t *dev); |
77 | 76 | ||
78 | static chardev_operations_t gxemul_ops = { |
77 | static chardev_operations_t gxemul_ops = { |
79 | .resume = gxemul_kbd_enable, |
78 | .resume = gxemul_kbd_enable, |
80 | .suspend = gxemul_kbd_disable, |
79 | .suspend = gxemul_kbd_disable, |
Line 131... | Line 130... | ||
131 | /** Putchar that works with gxemul. |
130 | /** Putchar that works with gxemul. |
132 | * |
131 | * |
133 | * @param dev Not used. |
132 | * @param dev Not used. |
134 | * @param ch Characted to be printed. |
133 | * @param ch Characted to be printed. |
135 | */ |
134 | */ |
136 | static void gxemul_write(chardev_t *dev, const char ch) |
135 | static void gxemul_write(chardev_t *dev, const char ch, bool silent) |
137 | { |
136 | { |
- | 137 | if (!silent) |
|
138 | *((char *) gxemul_hw_map.videoram) = ch; |
138 | *((char *) gxemul_hw_map.videoram) = ch; |
139 | } |
139 | } |
140 | 140 | ||
141 | /** Enables gxemul keyboard (interrupt unmasked). |
141 | /** Enables gxemul keyboard (interrupt unmasked). |
142 | * |
142 | * |
143 | * @param dev Not used. |
143 | * @param dev Not used. |
Line 181... | Line 181... | ||
181 | } |
181 | } |
182 | 182 | ||
183 | /** Process keyboard interrupt. |
183 | /** Process keyboard interrupt. |
184 | * |
184 | * |
185 | * @param irq IRQ information. |
185 | * @param irq IRQ information. |
186 | * @param arg Not used. |
- | |
187 | */ |
186 | */ |
188 | static void gxemul_irq_handler(irq_t *irq, void *arg, ...) |
187 | static void gxemul_irq_handler(irq_t *irq) |
189 | { |
188 | { |
190 | if ((irq->notif_cfg.notify) && (irq->notif_cfg.answerbox)) { |
- | |
191 | ipc_irq_send_notif(irq); |
- | |
192 | } else { |
- | |
193 | char ch = 0; |
189 | char ch = 0; |
194 | 190 | ||
195 | ch = *((char *) gxemul_hw_map.kbd); |
191 | ch = *((char *) gxemul_hw_map.kbd); |
196 | if (ch == '\r') { |
192 | if (ch == '\r') { |
197 | ch = '\n'; |
193 | ch = '\n'; |
198 | } |
- | |
199 | if (ch == 0x7f) { |
- | |
200 | ch = '\b'; |
- | |
201 | } |
- | |
202 | chardev_push_character(&console, ch); |
- | |
203 | } |
194 | } |
- | 195 | if (ch == 0x7f) { |
|
- | 196 | ch = '\b'; |
|
- | 197 | } |
|
- | 198 | chardev_push_character(&console, ch); |
|
204 | } |
199 | } |
205 | 200 | ||
206 | static irq_ownership_t gxemul_claim(void) |
201 | static irq_ownership_t gxemul_claim(irq_t *irq) |
207 | { |
202 | { |
208 | return IRQ_ACCEPT; |
203 | return IRQ_ACCEPT; |
209 | } |
204 | } |
210 | 205 | ||
211 | - | ||
212 | /** Acquire console back for kernel. */ |
- | |
213 | void gxemul_grab_console(void) |
- | |
214 | { |
- | |
215 | ipl_t ipl = interrupts_disable(); |
- | |
216 | spinlock_lock(&gxemul_console_irq.lock); |
- | |
217 | gxemul_console_irq.notif_cfg.notify = false; |
- | |
218 | spinlock_unlock(&gxemul_console_irq.lock); |
- | |
219 | interrupts_restore(ipl); |
- | |
220 | } |
- | |
221 | - | ||
222 | /** Return console to userspace. */ |
- | |
223 | void gxemul_release_console(void) |
- | |
224 | { |
- | |
225 | ipl_t ipl = interrupts_disable(); |
- | |
226 | spinlock_lock(&gxemul_console_irq.lock); |
- | |
227 | if (gxemul_console_irq.notif_cfg.answerbox) { |
- | |
228 | gxemul_console_irq.notif_cfg.notify = true; |
- | |
229 | } |
- | |
230 | spinlock_unlock(&gxemul_console_irq.lock); |
- | |
231 | interrupts_restore(ipl); |
- | |
232 | } |
- | |
233 | - | ||
234 | /** Initializes console object representing gxemul console. |
206 | /** Initializes console object representing gxemul console. |
235 | * |
207 | * |
236 | * @param devno device number. |
208 | * @param devno device number. |
237 | */ |
209 | */ |
238 | void gxemul_console_init(devno_t devno) |
210 | void gxemul_console_init(devno_t devno) |
Line 263... | Line 235... | ||
263 | static void gxemul_timer_start(uint32_t frequency) |
235 | static void gxemul_timer_start(uint32_t frequency) |
264 | { |
236 | { |
265 | *((uint32_t*) gxemul_hw_map.rtc_freq) = frequency; |
237 | *((uint32_t*) gxemul_hw_map.rtc_freq) = frequency; |
266 | } |
238 | } |
267 | 239 | ||
268 | static irq_ownership_t gxemul_timer_claim(void) |
240 | static irq_ownership_t gxemul_timer_claim(irq_t *irq) |
269 | { |
241 | { |
270 | return IRQ_ACCEPT; |
242 | return IRQ_ACCEPT; |
271 | } |
243 | } |
272 | 244 | ||
273 | /** Timer interrupt handler. |
245 | /** Timer interrupt handler. |
274 | * |
246 | * |
275 | * @param irq Interrupt information. |
247 | * @param irq Interrupt information. |
276 | * @param arg Not used. |
248 | * @param arg Not used. |
277 | */ |
249 | */ |
278 | static void gxemul_timer_irq_handler(irq_t *irq, void *arg, ...) |
250 | static void gxemul_timer_irq_handler(irq_t *irq) |
279 | { |
251 | { |
280 | /* |
252 | /* |
281 | * We are holding a lock which prevents preemption. |
253 | * We are holding a lock which prevents preemption. |
282 | * Release the lock, call clock() and reacquire the lock again. |
254 | * Release the lock, call clock() and reacquire the lock again. |
283 | */ |
255 | */ |
Line 367... | Line 339... | ||
367 | for (i = 0; i < GXEMUL_IRQC_MAX_IRQ; i++) { |
339 | for (i = 0; i < GXEMUL_IRQC_MAX_IRQ; i++) { |
368 | if (sources & (1 << i)) { |
340 | if (sources & (1 << i)) { |
369 | irq_t *irq = irq_dispatch_and_lock(i); |
341 | irq_t *irq = irq_dispatch_and_lock(i); |
370 | if (irq) { |
342 | if (irq) { |
371 | /* The IRQ handler was found. */ |
343 | /* The IRQ handler was found. */ |
372 | irq->handler(irq, irq->arg); |
344 | irq->handler(irq); |
373 | spinlock_unlock(&irq->lock); |
345 | spinlock_unlock(&irq->lock); |
374 | } else { |
346 | } else { |
375 | /* Spurious interrupt.*/ |
347 | /* Spurious interrupt.*/ |
376 | dprintf("cpu%d: spurious interrupt (inum=%d)\n", |
348 | dprintf("cpu%d: spurious interrupt (inum=%d)\n", |
377 | CPU->id, i); |
349 | CPU->id, i); |