Rev 4628 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 4628 | Rev 4629 | ||
---|---|---|---|
Line 1... | Line 1... | ||
1 | /* |
1 | /* |
2 | * Copyright (c) 2007 Michal Kebrt, Petr Stepan |
2 | * Copyright (c) 2009 Vineeth Pillai |
3 | * All rights reserved. |
3 | * All rights reserved. |
4 | * |
4 | * |
5 | * Redistribution and use in source and binary forms, with or without |
5 | * Redistribution and use in source and binary forms, with or without |
6 | * modification, are permitted provided that the following conditions |
6 | * modification, are permitted provided that the following conditions |
7 | * are met: |
7 | * are met: |
Line 35... | Line 35... | ||
35 | 35 | ||
36 | #include <interrupt.h> |
36 | #include <interrupt.h> |
37 | #include <ipc/irq.h> |
37 | #include <ipc/irq.h> |
38 | #include <console/chardev.h> |
38 | #include <console/chardev.h> |
39 | #include <arch/drivers/qemu.h> |
39 | #include <arch/drivers/qemu.h> |
- | 40 | #include <arch/drivers/pl050.h> |
|
40 | #include <console/console.h> |
41 | #include <console/console.h> |
41 | #include <sysinfo/sysinfo.h> |
42 | #include <sysinfo/sysinfo.h> |
42 | #include <print.h> |
43 | #include <print.h> |
43 | #include <ddi/device.h> |
44 | #include <ddi/device.h> |
44 | #include <mm/page.h> |
45 | #include <mm/page.h> |
Line 74... | Line 75... | ||
74 | /* IRQs */ |
75 | /* IRQs */ |
75 | #define QEMU_ICP_KBD_IRQ 3 |
76 | #define QEMU_ICP_KBD_IRQ 3 |
76 | #define QEMU_ICP_TIMER_IRQ 6 |
77 | #define QEMU_ICP_TIMER_IRQ 6 |
77 | 78 | ||
78 | static qemu_icp_hw_map_t qemu_icp_hw_map; |
79 | static qemu_icp_hw_map_t qemu_icp_hw_map; |
79 | static chardev_t console; |
- | |
80 | static irq_t qemu_icp_console_irq; |
- | |
81 | static irq_t qemu_icp_timer_irq; |
80 | static irq_t qemu_icp_timer_irq; |
82 | 81 | ||
83 | static bool hw_map_init_called = false; |
82 | static bool hw_map_init_called = false; |
84 | static bool vga_init = false; |
83 | static bool vga_init = false; |
85 | 84 | ||
86 | static void qemu_icp_kbd_enable(chardev_t *dev); |
- | |
87 | static void qemu_icp_kbd_disable(chardev_t *dev); |
- | |
88 | static void qemu_icp_write(chardev_t *dev, const char ch); |
- | |
89 | static char qemu_icp_do_read(chardev_t *dev); |
- | |
90 | void icp_vga_init(void); |
85 | void icp_vga_init(void); |
91 | 86 | ||
92 | static chardev_operations_t qemu_icp_ops = { |
- | |
93 | .resume = qemu_icp_kbd_enable, |
- | |
94 | .suspend = qemu_icp_kbd_disable, |
- | |
95 | .write = qemu_icp_write, |
- | |
96 | .read = qemu_icp_do_read, |
- | |
97 | }; |
- | |
98 | - | ||
99 | /** Initializes the vga |
87 | /** Initializes the vga |
100 | * |
88 | * |
101 | */ |
89 | */ |
102 | void icp_vga_init(void) |
90 | void icp_vga_init(void) |
103 | { |
91 | { |
Line 170... | Line 158... | ||
170 | 158 | ||
171 | hw_map_init_called = true; |
159 | hw_map_init_called = true; |
172 | } |
160 | } |
173 | 161 | ||
174 | 162 | ||
175 | /** Putchar that works with qemu_icp. |
- | |
176 | * |
- | |
177 | * @param dev Not used. |
- | |
178 | * @param ch Characted to be printed. |
- | |
179 | */ |
- | |
180 | static void qemu_icp_write(chardev_t *dev, const char ch) |
- | |
181 | { |
- | |
182 | *((char *) qemu_icp_hw_map.videoram) = ch; |
- | |
183 | } |
- | |
184 | - | ||
185 | /** Enables qemu_icp keyboard (interrupt unmasked). |
- | |
186 | * |
- | |
187 | * @param dev Not used. |
- | |
188 | * |
- | |
189 | * Called from getc(). |
- | |
190 | */ |
- | |
191 | static void qemu_icp_kbd_enable(chardev_t *dev) |
- | |
192 | { |
- | |
193 | qemu_icp_irqc_unmask(QEMU_ICP_KBD_IRQ); |
- | |
194 | } |
- | |
195 | - | ||
196 | /** Disables qemu_icp keyboard (interrupt masked). |
- | |
197 | * |
- | |
198 | * @param dev not used |
- | |
199 | * |
- | |
200 | * Called from getc(). |
- | |
201 | */ |
- | |
202 | static void qemu_icp_kbd_disable(chardev_t *dev) |
- | |
203 | { |
- | |
204 | qemu_icp_irqc_mask(QEMU_ICP_KBD_IRQ); |
- | |
205 | } |
- | |
206 | - | ||
207 | /** Read character using polling, assume interrupts disabled. |
- | |
208 | * |
- | |
209 | * @param dev Not used. |
- | |
210 | */ |
- | |
211 | static char qemu_icp_do_read(chardev_t *dev) |
- | |
212 | { |
- | |
213 | char ch; |
- | |
214 | - | ||
215 | while (1) { |
- | |
216 | ch = *((volatile char *) qemu_icp_hw_map.kbd_data); |
- | |
217 | if (ch) { |
- | |
218 | if (ch == '\r') |
- | |
219 | return '\n'; |
- | |
220 | if (ch == 0x7f) |
- | |
221 | return '\b'; |
- | |
222 | return ch; |
- | |
223 | } |
- | |
224 | } |
- | |
225 | } |
- | |
226 | - | ||
227 | /** Process keyboard interrupt. |
- | |
228 | * |
- | |
229 | * @param irq IRQ information. |
- | |
230 | * @param arg Not used. |
- | |
231 | */ |
- | |
232 | static void qemu_icp_irq_handler(irq_t *irq, void *arg, ...) |
- | |
233 | { |
- | |
234 | if ((irq->notif_cfg.notify) && (irq->notif_cfg.answerbox)) { |
- | |
235 | ipc_irq_send_notif(irq); |
- | |
236 | } else { |
- | |
237 | char ch = 0; |
- | |
238 | - | ||
239 | ch = *((char *) qemu_icp_hw_map.kbd_data); |
- | |
240 | if (ch == '\r') { |
- | |
241 | ch = '\n'; |
- | |
242 | } |
- | |
243 | if (ch == 0x7f) { |
- | |
244 | ch = '\b'; |
- | |
245 | } |
- | |
246 | chardev_push_character(&console, ch); |
- | |
247 | } |
- | |
248 | } |
- | |
249 | - | ||
250 | static irq_ownership_t qemu_icp_claim(void) |
- | |
251 | { |
- | |
252 | return IRQ_ACCEPT; |
- | |
253 | } |
- | |
254 | - | ||
255 | - | ||
256 | /** Acquire console back for kernel. */ |
163 | /** Acquire console back for kernel. */ |
257 | void qemu_icp_grab_console(void) |
164 | void qemu_icp_grab_console(void) |
258 | { |
165 | { |
259 | ipl_t ipl = interrupts_disable(); |
- | |
260 | spinlock_lock(&qemu_icp_console_irq.lock); |
- | |
261 | qemu_icp_console_irq.notif_cfg.notify = false; |
- | |
262 | spinlock_unlock(&qemu_icp_console_irq.lock); |
- | |
263 | interrupts_restore(ipl); |
166 | pl050_grab(); |
264 | } |
167 | } |
265 | 168 | ||
266 | /** Return console to userspace. */ |
169 | /** Return console to userspace. */ |
267 | void qemu_icp_release_console(void) |
170 | void qemu_icp_release_console(void) |
268 | { |
171 | { |
269 | ipl_t ipl = interrupts_disable(); |
- | |
270 | spinlock_lock(&qemu_icp_console_irq.lock); |
- | |
271 | if (qemu_icp_console_irq.notif_cfg.answerbox) { |
- | |
272 | qemu_icp_console_irq.notif_cfg.notify = true; |
- | |
273 | } |
- | |
274 | spinlock_unlock(&qemu_icp_console_irq.lock); |
- | |
275 | interrupts_restore(ipl); |
172 | pl050_release(); |
276 | } |
173 | } |
277 | 174 | ||
278 | /** Initializes console object representing qemu_icp console. |
175 | /** Initializes console object representing qemu_icp console. |
279 | * |
176 | * |
280 | * @param devno device number. |
177 | * @param devno device number. |
281 | */ |
178 | */ |
282 | void qemu_icp_console_init(devno_t devno) |
179 | void qemu_icp_console_init(devno_t devno) |
283 | { |
180 | { |
284 | chardev_initialize("qemu_icp_console", &console, &qemu_icp_ops); |
- | |
285 | stdin = &console; |
- | |
286 | stdout = &console; |
- | |
287 | 181 | ||
288 | qemu_icp_irqc_mask(QEMU_ICP_KBD_IRQ); |
182 | qemu_icp_irqc_mask(QEMU_ICP_KBD_IRQ); |
289 | irq_initialize(&qemu_icp_console_irq); |
- | |
290 | qemu_icp_console_irq.devno = devno; |
- | |
291 | qemu_icp_console_irq.inr = QEMU_ICP_KBD_IRQ; |
- | |
292 | qemu_icp_console_irq.claim = qemu_icp_claim; |
- | |
293 | qemu_icp_console_irq.handler = qemu_icp_irq_handler; |
183 | pl050_init(devno, QEMU_ICP_KBD_IRQ, QEMU_ICP_KBD, qemu_icp_hw_map.kbd_ctrl); |
294 | irq_register(&qemu_icp_console_irq); |
- | |
295 | - | ||
296 | *(char *)qemu_icp_hw_map.kbd_ctrl = 0x17; |
- | |
297 | - | ||
298 | qemu_icp_irqc_unmask(QEMU_ICP_KBD_IRQ); |
184 | qemu_icp_irqc_unmask(QEMU_ICP_KBD_IRQ); |
299 | - | ||
300 | sysinfo_set_item_val("kbd", NULL, true); |
- | |
301 | sysinfo_set_item_val("kbd.devno", NULL, devno); |
- | |
302 | sysinfo_set_item_val("kbd.inr", NULL, QEMU_ICP_KBD_IRQ); |
- | |
303 | sysinfo_set_item_val("kbd.address.virtual", NULL, qemu_icp_hw_map.kbd_data); |
- | |
304 | } |
185 | } |
305 | 186 | ||
306 | /** Starts qemu_icp Real Time Clock device, which asserts regular interrupts. |
187 | /** Starts qemu_icp Real Time Clock device, which asserts regular interrupts. |
307 | * |
188 | * |
308 | * @param frequency Interrupts frequency (0 disables RTC). |
189 | * @param frequency Interrupts frequency (0 disables RTC). |