Fix remote screen check in graphic equalizer, so that it can be used on logf-enabled...
[Rockbox.git] / firmware / kernel.c
blobb18b92327b46599d66d87abdbd379814d37bd715
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2002 by Björn Stenberg
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
19 #include <stdlib.h>
20 #include <string.h>
21 #include "config.h"
22 #include "kernel.h"
23 #include "thread.h"
24 #include "cpu.h"
25 #include "system.h"
26 #include "panic.h"
28 #if ((CONFIG_CPU != PP5020) && (CONFIG_CPU != PP5002)) || !defined(BOOTLOADER)
29 long current_tick = 0;
30 #endif
32 static void (*tick_funcs[MAX_NUM_TICK_TASKS])(void);
34 /* This array holds all queues that are initiated. It is used for broadcast. */
35 static struct event_queue *all_queues[32];
36 static int num_queues;
38 void queue_wait(struct event_queue *q, struct event *ev) ICODE_ATTR;
40 /****************************************************************************
41 * Standard kernel stuff
42 ****************************************************************************/
43 void kernel_init(void)
45 /* Init the threading API */
46 init_threads();
48 memset(tick_funcs, 0, sizeof(tick_funcs));
50 num_queues = 0;
51 memset(all_queues, 0, sizeof(all_queues));
53 tick_start(1000/HZ);
56 void sleep(int ticks)
58 #if CONFIG_CPU == S3C2440 && defined(BOOTLOADER)
59 int counter;
60 TCON &= ~(1 << 20); // stop timer 4
61 // TODO: this constant depends on dividers settings inherited from
62 // firmware. Set them explicitly somwhere.
63 TCNTB4 = 12193 * ticks / HZ;
64 TCON |= 1 << 21; // set manual bit
65 TCON &= ~(1 << 21); // reset manual bit
66 TCON &= ~(1 << 22); //autoreload Off
67 TCON |= (1 << 20); // start timer 4
68 do {
69 counter = TCNTO4;
70 } while(counter > 0);
72 #else
73 sleep_thread(ticks);
74 #endif
77 void yield(void)
79 #if (CONFIG_CPU == S3C2440 || defined(ELIO_TPJ1022) && defined(BOOTLOADER))
80 /* Some targets don't like yielding in the bootloader */
81 #else
82 switch_thread(true, NULL);
83 #endif
86 /****************************************************************************
87 * Queue handling stuff
88 ****************************************************************************/
89 void queue_init(struct event_queue *q, bool register_queue)
91 q->read = 0;
92 q->write = 0;
93 q->thread = NULL;
95 if (register_queue)
97 /* Add it to the all_queues array */
98 all_queues[num_queues++] = q;
102 void queue_delete(struct event_queue *q)
104 int i;
105 bool found = false;
107 wakeup_thread(&q->thread);
109 /* Find the queue to be deleted */
110 for(i = 0;i < num_queues;i++)
112 if(all_queues[i] == q)
114 found = true;
115 break;
119 if(found)
121 /* Move the following queues up in the list */
122 for(;i < num_queues-1;i++)
124 all_queues[i] = all_queues[i+1];
127 num_queues--;
131 void queue_wait(struct event_queue *q, struct event *ev)
133 if (q->read == q->write)
135 block_thread(&q->thread, 0);
138 *ev = q->events[(q->read++) & QUEUE_LENGTH_MASK];
141 void queue_wait_w_tmo(struct event_queue *q, struct event *ev, int ticks)
143 if (q->read == q->write && ticks > 0)
145 block_thread(&q->thread, ticks);
148 if (q->read != q->write)
150 *ev = q->events[(q->read++) & QUEUE_LENGTH_MASK];
152 else
154 ev->id = SYS_TIMEOUT;
158 void queue_post(struct event_queue *q, long id, void *data)
160 int wr;
161 int oldlevel;
163 oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL);
164 wr = (q->write++) & QUEUE_LENGTH_MASK;
166 q->events[wr].id = id;
167 q->events[wr].data = data;
169 wakeup_thread(&q->thread);
171 set_irq_level(oldlevel);
174 bool queue_empty(const struct event_queue* q)
176 return ( q->read == q->write );
179 void queue_clear(struct event_queue* q)
181 int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL);
182 q->read = 0;
183 q->write = 0;
184 set_irq_level(oldlevel);
187 void queue_remove_from_head(struct event_queue *q, long id)
189 int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL);
191 while (q->read != q->write &&
192 q->events[(q->read) & QUEUE_LENGTH_MASK].id == id)
194 q->read++;
197 set_irq_level(oldlevel);
200 int queue_broadcast(long id, void *data)
202 int i;
204 for(i = 0;i < num_queues;i++)
206 queue_post(all_queues[i], id, data);
209 return num_queues;
212 /****************************************************************************
213 * Timer tick
214 ****************************************************************************/
215 #if CONFIG_CPU == SH7034
216 void tick_start(unsigned int interval_in_ms)
218 unsigned long count;
220 count = CPU_FREQ * interval_in_ms / 1000 / 8;
222 if(count > 0x10000)
224 panicf("Error! The tick interval is too long (%d ms)\n",
225 interval_in_ms);
226 return;
229 /* We are using timer 0 */
231 TSTR &= ~0x01; /* Stop the timer */
232 TSNC &= ~0x01; /* No synchronization */
233 TMDR &= ~0x01; /* Operate normally */
235 TCNT0 = 0; /* Start counting at 0 */
236 GRA0 = (unsigned short)(count - 1);
237 TCR0 = 0x23; /* Clear at GRA match, sysclock/8 */
239 /* Enable interrupt on level 1 */
240 IPRC = (IPRC & ~0x00f0) | 0x0010;
242 TSR0 &= ~0x01;
243 TIER0 = 0xf9; /* Enable GRA match interrupt */
245 TSTR |= 0x01; /* Start timer 1 */
248 void IMIA0(void) __attribute__ ((interrupt_handler));
249 void IMIA0(void)
251 int i;
253 /* Run through the list of tick tasks */
254 for(i = 0;i < MAX_NUM_TICK_TASKS;i++)
256 if(tick_funcs[i])
258 tick_funcs[i]();
262 current_tick++;
264 TSR0 &= ~0x01;
266 #elif defined(CPU_COLDFIRE)
267 void tick_start(unsigned int interval_in_ms)
269 unsigned long count;
270 int prescale;
272 count = CPU_FREQ/2 * interval_in_ms / 1000 / 16;
274 if(count > 0x10000)
276 panicf("Error! The tick interval is too long (%d ms)\n",
277 interval_in_ms);
278 return;
281 prescale = cpu_frequency / CPU_FREQ;
282 /* Note: The prescaler is later adjusted on-the-fly on CPU frequency
283 changes within timer.c */
285 /* We are using timer 0 */
287 TRR0 = (unsigned short)(count - 1); /* The reference count */
288 TCN0 = 0; /* reset the timer */
289 TMR0 = 0x001d | ((unsigned short)(prescale - 1) << 8);
290 /* restart, CLK/16, enabled, prescaler */
292 TER0 = 0xff; /* Clear all events */
294 ICR1 = 0x8c; /* Interrupt on level 3.0 */
295 IMR &= ~0x200;
298 void TIMER0(void) __attribute__ ((interrupt_handler));
299 void TIMER0(void)
301 int i;
303 /* Run through the list of tick tasks */
304 for(i = 0;i < MAX_NUM_TICK_TASKS;i++)
306 if(tick_funcs[i])
308 tick_funcs[i]();
312 current_tick++;
314 TER0 = 0xff; /* Clear all events */
317 #elif CONFIG_CPU == TCC730
319 void TIMER0(void)
321 int i;
323 /* Keep alive (?)
324 * If this is not done, power goes down when DC is unplugged.
326 if (current_tick % 2 == 0)
327 P8 |= 1;
328 else
329 P8 &= ~1;
331 /* Run through the list of tick tasks */
332 for(i = 0;i < MAX_NUM_TICK_TASKS;i++)
334 if(tick_funcs[i])
336 tick_funcs[i]();
340 current_tick++;
342 /* re-enable timer by clearing the counter */
343 TACON |= 0x80;
346 void tick_start(unsigned int interval_in_ms)
348 long count;
349 count = (long)FREQ * (long)interval_in_ms / 1000 / 16;
351 if(count > 0xffffL)
353 panicf("Error! The tick interval is too long (%dms->%lx)\n",
354 interval_in_ms, count);
355 return;
358 /* Use timer A */
359 TAPRE = 0x0;
360 TADATA = count;
362 TACON = 0x89;
363 /* counter clear; */
364 /* interval mode; */
365 /* TICS = F(osc) / 16 */
366 /* TCS = internal clock */
367 /* enable */
369 /* enable the interrupt */
370 interrupt_vector[2] = TIMER0;
371 IMR0 |= (1<<2);
374 #elif defined(CPU_PP)
376 #ifndef BOOTLOADER
377 void TIMER1(void)
379 int i;
381 TIMER1_VAL; /* Read value to ack IRQ */
382 /* Run through the list of tick tasks */
383 for (i = 0;i < MAX_NUM_TICK_TASKS;i++)
385 if (tick_funcs[i])
387 tick_funcs[i]();
391 current_tick++;
393 #endif
395 void tick_start(unsigned int interval_in_ms)
397 #ifndef BOOTLOADER
398 TIMER1_CFG = 0x0;
399 TIMER1_VAL;
400 /* enable timer */
401 TIMER1_CFG = 0xc0000000 | (interval_in_ms*1000 - 1);
402 /* unmask interrupt source */
403 CPU_INT_EN = TIMER1_MASK;
404 #else
405 /* We don't enable interrupts in the bootloader */
406 (void)interval_in_ms;
407 #endif
410 #elif CONFIG_CPU == PNX0101
412 void timer_handler(void)
414 int i;
416 /* Run through the list of tick tasks */
417 for(i = 0;i < MAX_NUM_TICK_TASKS;i++)
419 if(tick_funcs[i])
420 tick_funcs[i]();
423 current_tick++;
425 TIMERR0C = 1;
428 void tick_start(unsigned int interval_in_ms)
430 TIMERR08 &= ~0x80;
431 TIMERR0C = 1;
432 TIMERR08 &= ~0x80;
433 TIMERR08 |= 0x40;
434 TIMERR00 = 3000000 * interval_in_ms / 1000;
435 TIMERR08 &= ~0xc;
436 TIMERR0C = 1;
438 irq_set_int_handler(4, timer_handler);
439 irq_enable_int(4);
441 TIMERR08 |= 0x80;
443 #elif CONFIG_CPU == S3C2440
444 void tick_start(unsigned int interval_in_ms)
446 unsigned long count;
448 /* period = (n + 1) / 128 , n = tick time count (1~127)*/
449 count = interval_in_ms / 1000 * 128 - 1;
451 if(count > 127)
453 panicf("Error! The tick interval is too long (%d ms)\n",
454 interval_in_ms);
455 return;
458 /* Disable the tick */
459 TICNT &= ~(1<<7);
460 /* Set the count value */
461 TICNT |= count;
462 /* Start up the ticker */
463 TICNT |= (1<<7);
465 /* need interrupt handler ??? */
468 #endif
470 int tick_add_task(void (*f)(void))
472 int i;
473 int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL);
475 /* Add a task if there is room */
476 for(i = 0;i < MAX_NUM_TICK_TASKS;i++)
478 if(tick_funcs[i] == NULL)
480 tick_funcs[i] = f;
481 set_irq_level(oldlevel);
482 return 0;
485 set_irq_level(oldlevel);
486 panicf("Error! tick_add_task(): out of tasks");
487 return -1;
490 int tick_remove_task(void (*f)(void))
492 int i;
493 int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL);
495 /* Remove a task if it is there */
496 for(i = 0;i < MAX_NUM_TICK_TASKS;i++)
498 if(tick_funcs[i] == f)
500 tick_funcs[i] = NULL;
501 set_irq_level(oldlevel);
502 return 0;
506 set_irq_level(oldlevel);
507 return -1;
510 #ifndef SIMULATOR
512 * Simulator versions in uisimulator/SIMVER/
515 /****************************************************************************
516 * Simple mutex functions
517 ****************************************************************************/
518 void mutex_init(struct mutex *m)
520 m->locked = false;
521 m->thread = NULL;
524 void mutex_lock(struct mutex *m)
526 if (m->locked)
528 /* Wait until the lock is open... */
529 block_thread(&m->thread, 0);
532 /* ...and lock it */
533 m->locked = true;
536 void mutex_unlock(struct mutex *m)
538 if (m->thread == NULL)
539 m->locked = false;
540 else
541 wakeup_thread(&m->thread);
544 #endif