Rev 2412 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 2412 | Rev 2414 | ||
---|---|---|---|
Line 44... | Line 44... | ||
44 | #include <mm/page.h> |
44 | #include <mm/page.h> |
45 | #include <arch/machine.h> |
45 | #include <arch/machine.h> |
46 | #include <arch/debug/print.h> |
46 | #include <arch/debug/print.h> |
47 | 47 | ||
48 | 48 | ||
49 | /** Addresses of devices. */ |
49 | /* Addresses of devices. */ |
50 | #define GXEMUL_VIDEORAM 0x10000000 |
50 | #define GXEMUL_VIDEORAM 0x10000000 |
51 | #define GXEMUL_KBD 0x10000000 |
51 | #define GXEMUL_KBD 0x10000000 |
52 | #define GXEMUL_HALT_OFFSET 0x10 |
52 | #define GXEMUL_HALT_OFFSET 0x10 |
53 | #define GXEMUL_RTC 0x15000000 |
53 | #define GXEMUL_RTC 0x15000000 |
54 | #define GXEMUL_RTC_FREQ_OFFSET 0x100 |
54 | #define GXEMUL_RTC_FREQ_OFFSET 0x100 |
Line 59... | Line 59... | ||
59 | #define GXEMUL_MP 0x11000000 |
59 | #define GXEMUL_MP 0x11000000 |
60 | #define GXEMUL_MP_MEMSIZE_OFFSET 0x0090 |
60 | #define GXEMUL_MP_MEMSIZE_OFFSET 0x0090 |
61 | #define GXEMUL_FB 0x12000000 |
61 | #define GXEMUL_FB 0x12000000 |
62 | 62 | ||
63 | 63 | ||
64 | /** IRQs */ |
64 | /* IRQs */ |
65 | #define GXEMUL_KBD_IRQ 2 |
65 | #define GXEMUL_KBD_IRQ 2 |
66 | #define GXEMUL_TIMER_IRQ 4 |
66 | #define GXEMUL_TIMER_IRQ 4 |
67 | 67 | ||
68 | static gxemul_hw_map_t gxemul_hw_map; |
68 | static gxemul_hw_map_t gxemul_hw_map; |
69 | static chardev_t console; |
69 | static chardev_t console; |
70 | static irq_t gxemul_irq; |
70 | static irq_t gxemul_console_irq; |
71 | static irq_t gxemul_timer_irq; |
71 | static irq_t gxemul_timer_irq; |
72 | 72 | ||
73 | static bool hw_map_init_called = false; |
73 | static bool hw_map_init_called = false; |
74 | 74 | ||
- | 75 | static void gxemul_kbd_enable(chardev_t *dev); |
|
- | 76 | static void gxemul_kbd_disable(chardev_t *dev); |
|
75 | static void gxemul_write(chardev_t *dev, const char ch); |
77 | static void gxemul_write(chardev_t *dev, const char ch); |
76 | static void gxemul_enable(chardev_t *dev); |
- | |
77 | static void gxemul_disable(chardev_t *dev); |
- | |
78 | static char gxemul_do_read(chardev_t *dev); |
78 | static char gxemul_do_read(chardev_t *dev); |
79 | 79 | ||
80 | static chardev_operations_t gxemul_ops = { |
80 | static chardev_operations_t gxemul_ops = { |
81 | .resume = gxemul_enable, |
81 | .resume = gxemul_kbd_enable, |
82 | .suspend = gxemul_disable, |
82 | .suspend = gxemul_kbd_disable, |
83 | .write = gxemul_write, |
83 | .write = gxemul_write, |
84 | .read = gxemul_do_read, |
84 | .read = gxemul_do_read, |
85 | }; |
85 | }; |
86 | 86 | ||
87 | 87 | ||
Line 127... | Line 127... | ||
127 | 127 | ||
128 | hw_map_init_called = true; |
128 | hw_map_init_called = true; |
129 | } |
129 | } |
130 | 130 | ||
131 | 131 | ||
132 | /** Putchar that works with gxemul */ |
132 | /** Putchar that works with gxemul. |
- | 133 | * |
|
- | 134 | * @param dev Not used. |
|
- | 135 | * @param ch Characted to be printed. |
|
- | 136 | */ |
|
133 | static void gxemul_write(chardev_t *dev, const char ch) |
137 | static void gxemul_write(chardev_t *dev, const char ch) |
134 | { |
138 | { |
135 | *((char *) gxemul_hw_map.videoram) = ch; |
139 | *((char *) gxemul_hw_map.videoram) = ch; |
136 | } |
140 | } |
137 | 141 | ||
138 | 142 | ||
- | 143 | /** Enables gxemul keyboard (interrupt unmasked). |
|
- | 144 | * |
|
- | 145 | * @param dev Not used. |
|
- | 146 | * |
|
139 | /* Called from getc(). */ |
147 | * Called from getc(). |
- | 148 | */ |
|
140 | static void gxemul_enable(chardev_t *dev) |
149 | static void gxemul_kbd_enable(chardev_t *dev) |
141 | { |
150 | { |
142 | gxemul_irqc_unmask(GXEMUL_KBD_IRQ); |
151 | gxemul_irqc_unmask(GXEMUL_KBD_IRQ); |
143 | } |
152 | } |
144 | 153 | ||
145 | 154 | ||
- | 155 | /** Disables gxemul keyboard (interrupt masked). |
|
- | 156 | * |
|
- | 157 | * @param dev not used |
|
- | 158 | * |
|
146 | /* Called from getc(). */ |
159 | * Called from getc(). |
- | 160 | */ |
|
147 | static void gxemul_disable(chardev_t *dev) |
161 | static void gxemul_kbd_disable(chardev_t *dev) |
148 | { |
162 | { |
149 | gxemul_irqc_mask(GXEMUL_KBD_IRQ); |
163 | gxemul_irqc_mask(GXEMUL_KBD_IRQ); |
150 | } |
164 | } |
151 | 165 | ||
152 | 166 | ||
Line 169... | Line 183... | ||
169 | } |
183 | } |
170 | } |
184 | } |
171 | } |
185 | } |
172 | 186 | ||
173 | 187 | ||
174 | /** Process keyboard interrupt. */ |
188 | /** Process keyboard interrupt. |
- | 189 | * |
|
- | 190 | * @param irq IRQ information. |
|
- | 191 | * @param arg Not used. |
|
- | 192 | */ |
|
175 | static void gxemul_irq_handler(irq_t *irq, void *arg, ...) |
193 | static void gxemul_irq_handler(irq_t *irq, void *arg, ...) |
176 | { |
194 | { |
177 | if ((irq->notif_cfg.notify) && (irq->notif_cfg.answerbox)) { |
195 | if ((irq->notif_cfg.notify) && (irq->notif_cfg.answerbox)) { |
178 | ipc_irq_send_notif(irq); |
196 | ipc_irq_send_notif(irq); |
179 | } else { |
197 | } else { |
Line 199... | Line 217... | ||
199 | 217 | ||
200 | /** Acquire console back for kernel. */ |
218 | /** Acquire console back for kernel. */ |
201 | void gxemul_grab_console(void) |
219 | void gxemul_grab_console(void) |
202 | { |
220 | { |
203 | ipl_t ipl = interrupts_disable(); |
221 | ipl_t ipl = interrupts_disable(); |
204 | spinlock_lock(&gxemul_irq.lock); |
222 | spinlock_lock(&gxemul_console_irq.lock); |
205 | gxemul_irq.notif_cfg.notify = false; |
223 | gxemul_console_irq.notif_cfg.notify = false; |
206 | spinlock_unlock(&gxemul_irq.lock); |
224 | spinlock_unlock(&gxemul_console_irq.lock); |
207 | interrupts_restore(ipl); |
225 | interrupts_restore(ipl); |
208 | } |
226 | } |
209 | 227 | ||
210 | 228 | ||
211 | /** Return console to userspace. */ |
229 | /** Return console to userspace. */ |
212 | void gxemul_release_console(void) |
230 | void gxemul_release_console(void) |
213 | { |
231 | { |
214 | ipl_t ipl = interrupts_disable(); |
232 | ipl_t ipl = interrupts_disable(); |
215 | spinlock_lock(&gxemul_irq.lock); |
233 | spinlock_lock(&gxemul_console_irq.lock); |
216 | if (gxemul_irq.notif_cfg.answerbox) { |
234 | if (gxemul_console_irq.notif_cfg.answerbox) { |
217 | gxemul_irq.notif_cfg.notify = true; |
235 | gxemul_console_irq.notif_cfg.notify = true; |
218 | } |
236 | } |
219 | spinlock_unlock(&gxemul_irq.lock); |
237 | spinlock_unlock(&gxemul_console_irq.lock); |
220 | interrupts_restore(ipl); |
238 | interrupts_restore(ipl); |
221 | } |
239 | } |
222 | 240 | ||
223 | 241 | ||
224 | /** Initializes console object representing gxemul console. |
242 | /** Initializes console object representing gxemul console. |
Line 229... | Line 247... | ||
229 | { |
247 | { |
230 | chardev_initialize("gxemul_console", &console, &gxemul_ops); |
248 | chardev_initialize("gxemul_console", &console, &gxemul_ops); |
231 | stdin = &console; |
249 | stdin = &console; |
232 | stdout = &console; |
250 | stdout = &console; |
233 | 251 | ||
234 | irq_initialize(&gxemul_irq); |
252 | irq_initialize(&gxemul_console_irq); |
235 | gxemul_irq.devno = devno; |
253 | gxemul_console_irq.devno = devno; |
236 | gxemul_irq.inr = GXEMUL_KBD_IRQ; |
254 | gxemul_console_irq.inr = GXEMUL_KBD_IRQ; |
237 | gxemul_irq.claim = gxemul_claim; |
255 | gxemul_console_irq.claim = gxemul_claim; |
238 | gxemul_irq.handler = gxemul_irq_handler; |
256 | gxemul_console_irq.handler = gxemul_irq_handler; |
239 | irq_register(&gxemul_irq); |
257 | irq_register(&gxemul_console_irq); |
240 | 258 | ||
241 | gxemul_irqc_unmask(GXEMUL_KBD_IRQ); |
259 | gxemul_irqc_unmask(GXEMUL_KBD_IRQ); |
242 | 260 | ||
243 | sysinfo_set_item_val("kbd", NULL, true); |
261 | sysinfo_set_item_val("kbd", NULL, true); |
244 | sysinfo_set_item_val("kbd.devno", NULL, devno); |
262 | sysinfo_set_item_val("kbd.devno", NULL, devno); |
Line 269... | Line 287... | ||
269 | * @param irq Interrupt information. |
287 | * @param irq Interrupt information. |
270 | * @param arg Not used. |
288 | * @param arg Not used. |
271 | */ |
289 | */ |
272 | static void gxemul_timer_irq_handler(irq_t *irq, void *arg, ...) |
290 | static void gxemul_timer_irq_handler(irq_t *irq, void *arg, ...) |
273 | { |
291 | { |
274 | /* TODO time drifts ?? |
- | |
275 | unsigned long drift; |
- | |
276 | - | ||
277 | drift = cp0_count_read() - nextcount; |
- | |
278 | while (drift > cp0_compare_value) { |
- | |
279 | drift -= cp0_compare_value; |
- | |
280 | CPU->missed_clock_ticks++; |
- | |
281 | } |
- | |
282 | nextcount = cp0_count_read() + cp0_compare_value - drift; |
- | |
283 | cp0_compare_write(nextcount); |
- | |
284 | */ |
- | |
285 | - | ||
286 | /* |
292 | /* |
287 | * We are holding a lock which prevents preemption. |
293 | * We are holding a lock which prevents preemption. |
288 | * Release the lock, call clock() and reacquire the lock again. |
294 | * Release the lock, call clock() and reacquire the lock again. |
289 | */ |
295 | */ |
290 | spinlock_unlock(&irq->lock); |
296 | spinlock_unlock(&irq->lock); |
291 | clock(); |
297 | clock(); |
292 | spinlock_lock(&irq->lock); |
298 | spinlock_lock(&irq->lock); |
293 | 299 | ||
294 | /* acknowledge tick */ |
300 | /* acknowledge tick */ |
295 | *(uint32_t*) gxemul_hw_map.rtc_ack = 0; |
301 | *(uint32_t*) gxemul_hw_map.rtc_ack = 0; |
296 | - | ||
297 | /* TODO what's that? * |
- | |
298 | if (virtual_timer_fnc != NULL) |
- | |
299 | virtual_timer_fnc(); |
- | |
300 | */ |
- | |
301 | } |
302 | } |
302 | 303 | ||
303 | 304 | ||
304 | /** Initializes and registers timer interrupt handler. */ |
305 | /** Initializes and registers timer interrupt handler. */ |
305 | static void gxemul_timer_irq_init() |
306 | static void gxemul_timer_irq_init() |