1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
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 ****************************************************************************/
28 #if !defined(CPU_PP) || !defined(BOOTLOADER)
29 long current_tick NOCACHEDATA_ATTR
= 0;
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] NOCACHEBSS_ATTR
;
36 static int num_queues NOCACHEBSS_ATTR
;
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 */
48 if(CURRENT_CORE
== CPU
)
50 memset(tick_funcs
, 0, sizeof(tick_funcs
));
53 memset(all_queues
, 0, sizeof(all_queues
));
61 #if CONFIG_CPU == S3C2440 && defined(BOOTLOADER)
63 TCON
&= ~(1 << 20); // stop timer 4
64 // TODO: this constant depends on dividers settings inherited from
65 // firmware. Set them explicitly somwhere.
66 TCNTB4
= 12193 * ticks
/ HZ
;
67 TCON
|= 1 << 21; // set manual bit
68 TCON
&= ~(1 << 21); // reset manual bit
69 TCON
&= ~(1 << 22); //autoreload Off
70 TCON
|= (1 << 20); // start timer 4
75 #elif defined(CPU_PP) && defined(BOOTLOADER)
76 unsigned stop
= USEC_TIMER
+ ticks
* (1000000/HZ
);
77 while (TIME_BEFORE(USEC_TIMER
, stop
))
78 switch_thread(true,NULL
);
86 #if ((CONFIG_CPU == S3C2440 || defined(ELIO_TPJ1022)) && defined(BOOTLOADER))
87 /* Some targets don't like yielding in the bootloader */
89 switch_thread(true, NULL
);
93 /****************************************************************************
94 * Queue handling stuff
95 ****************************************************************************/
97 #ifdef HAVE_EXTENDED_MESSAGING_AND_NAME
98 /* Moves waiting thread's descriptor to the current sender when a
99 message is dequeued */
100 static void queue_fetch_sender(struct queue_sender_list
*send
,
103 /* Disable interrupts to protect against collision in this slot */
104 int old_level
= set_irq_level(HIGHEST_IRQ_LEVEL
);
105 struct thread_entry
**spp
= &send
->senders
[i
];
109 send
->curr_sender
= *spp
;
113 set_irq_level(old_level
);
116 /* Puts the specified return value in the waiting thread's return value
117 * and wakes the thread.
118 * 1) A sender should be confirmed to exist before calling which makes it
119 * more efficent to reject the majority of cases that don't need this
121 * 2) Requires interrupts disabled since queue overflows can cause posts
122 * from interrupt handlers to wake threads. Not doing so could cause
123 * an attempt at multiple wakes or other problems.
125 static void queue_release_sender(struct thread_entry
**sender
,
128 (*sender
)->retval
= retval
;
129 wakeup_thread_irq_safe(sender
);
131 /* This should _never_ happen - there must never be multiple
132 threads in this list and it is a corrupt state */
134 panicf("Queue: send slot ovf");
138 /* Releases any waiting threads that are queued with queue_send -
140 * Disable IRQs before calling since it uses queue_release_sender.
142 static void queue_release_all_senders(struct event_queue
*q
)
147 for(i
= q
->read
; i
!= q
->write
; i
++)
149 struct thread_entry
**spp
=
150 &q
->send
->senders
[i
& QUEUE_LENGTH_MASK
];
154 queue_release_sender(spp
, 0);
160 /* Enables queue_send on the specified queue - caller allocates the extra
162 void queue_enable_queue_send(struct event_queue
*q
,
163 struct queue_sender_list
*send
)
166 memset(send
, 0, sizeof(struct queue_sender_list
));
168 #endif /* HAVE_EXTENDED_MESSAGING_AND_NAME */
171 void queue_init(struct event_queue
*q
, bool register_queue
)
179 #ifdef HAVE_EXTENDED_MESSAGING_AND_NAME
180 q
->send
= NULL
; /* No message sending by default */
185 /* Add it to the all_queues array */
186 all_queues
[num_queues
++] = q
;
192 * If IRQ mode is enabled, some core-wise locking mechanisms are disabled
193 * causing accessing queue to be no longer thread safe from the other core.
194 * However, that locking mechanism would also kill IRQ handlers.
196 * @param q struct of an event_queue
197 * @param state enable/disable IRQ mode
198 * @default state disabled
200 void queue_set_irq_safe(struct event_queue
*q
, bool state
)
206 void queue_delete(struct event_queue
*q
)
212 wakeup_thread(&q
->thread
);
214 /* Find the queue to be deleted */
215 for(i
= 0;i
< num_queues
;i
++)
217 if(all_queues
[i
] == q
)
226 #ifdef HAVE_EXTENDED_MESSAGING_AND_NAME
227 /* Release waiting threads and reply to any dequeued message
229 int level
= set_irq_level(HIGHEST_IRQ_LEVEL
);
230 queue_release_all_senders(q
);
231 queue_reply(q
, NULL
);
232 set_irq_level(level
);
234 /* Move the following queues up in the list */
235 for(;i
< num_queues
-1;i
++)
237 all_queues
[i
] = all_queues
[i
+1];
246 void queue_wait(struct event_queue
*q
, struct event
*ev
)
252 if (q
->read
== q
->write
)
254 block_thread(&q
->thread
);
258 rd
= q
->read
++ & QUEUE_LENGTH_MASK
;
261 #ifdef HAVE_EXTENDED_MESSAGING_AND_NAME
262 if(q
->send
&& q
->send
->senders
[rd
])
264 /* Get data for a waiting thread if one */
265 queue_fetch_sender(q
->send
, rd
);
272 void queue_wait_w_tmo(struct event_queue
*q
, struct event
*ev
, int ticks
)
276 if (q
->read
== q
->write
&& ticks
> 0)
278 block_thread_w_tmo(&q
->thread
, ticks
);
282 if (q
->read
!= q
->write
)
284 unsigned int rd
= q
->read
++ & QUEUE_LENGTH_MASK
;
287 #ifdef HAVE_EXTENDED_MESSAGING_AND_NAME
288 if(q
->send
&& q
->send
->senders
[rd
])
290 /* Get data for a waiting thread if one */
291 queue_fetch_sender(q
->send
, rd
);
297 ev
->id
= SYS_TIMEOUT
;
303 void queue_post(struct event_queue
*q
, long id
, intptr_t data
)
305 int oldlevel
= set_irq_level(HIGHEST_IRQ_LEVEL
);
313 wr
= q
->write
++ & QUEUE_LENGTH_MASK
;
315 q
->events
[wr
].id
= id
;
316 q
->events
[wr
].data
= data
;
318 #ifdef HAVE_EXTENDED_MESSAGING_AND_NAME
321 struct thread_entry
**spp
= &q
->send
->senders
[wr
];
325 /* overflow protect - unblock any thread waiting at this index */
326 queue_release_sender(spp
, 0);
331 wakeup_thread_irq_safe(&q
->thread
);
336 set_irq_level(oldlevel
);
340 #ifdef HAVE_EXTENDED_MESSAGING_AND_NAME
341 /* No wakeup_thread_irq_safe here because IRQ handlers are not allowed
342 use of this function - we only aim to protect the queue integrity by
344 intptr_t queue_send(struct event_queue
*q
, long id
, intptr_t data
)
346 int oldlevel
= set_irq_level(HIGHEST_IRQ_LEVEL
);
351 wr
= q
->write
++ & QUEUE_LENGTH_MASK
;
353 q
->events
[wr
].id
= id
;
354 q
->events
[wr
].data
= data
;
358 struct thread_entry
**spp
= &q
->send
->senders
[wr
];
362 /* overflow protect - unblock any thread waiting at this index */
363 queue_release_sender(spp
, 0);
366 wakeup_thread(&q
->thread
);
367 set_irq_level_and_block_thread(spp
, oldlevel
);
368 return thread_get_current()->retval
;
371 /* Function as queue_post if sending is not enabled */
372 wakeup_thread(&q
->thread
);
374 set_irq_level(oldlevel
);
379 #if 0 /* not used now but probably will be later */
380 /* Query if the last message dequeued was added by queue_send or not */
381 bool queue_in_queue_send(struct event_queue
*q
)
383 return q
->send
&& q
->send
->curr_sender
;
387 /* Replies with retval to any dequeued message sent with queue_send */
388 void queue_reply(struct event_queue
*q
, intptr_t retval
)
391 if(q
->send
&& q
->send
->curr_sender
)
393 int level
= set_irq_level(HIGHEST_IRQ_LEVEL
);
394 if(q
->send
->curr_sender
)
396 queue_release_sender(&q
->send
->curr_sender
, retval
);
398 set_irq_level(level
);
402 #endif /* HAVE_EXTENDED_MESSAGING_AND_NAME */
404 bool queue_empty(const struct event_queue
* q
)
413 is_empty
= ( q
->read
== q
->write
);
422 void queue_clear(struct event_queue
* q
)
424 int oldlevel
= set_irq_level(HIGHEST_IRQ_LEVEL
);
431 #ifdef HAVE_EXTENDED_MESSAGING_AND_NAME
432 /* Release all thread waiting in the queue for a reply -
433 dequeued sent message will be handled by owning thread */
434 queue_release_all_senders(q
);
445 set_irq_level(oldlevel
);
448 void queue_remove_from_head(struct event_queue
*q
, long id
)
450 int oldlevel
= set_irq_level(HIGHEST_IRQ_LEVEL
);
457 while(q
->read
!= q
->write
)
459 unsigned int rd
= q
->read
& QUEUE_LENGTH_MASK
;
461 if(q
->events
[rd
].id
!= id
)
466 #ifdef HAVE_EXTENDED_MESSAGING_AND_NAME
469 struct thread_entry
**spp
= &q
->send
->senders
[rd
];
473 /* Release any thread waiting on this message */
474 queue_release_sender(spp
, 0);
486 set_irq_level(oldlevel
);
490 * The number of events waiting in the queue.
492 * @param struct of event_queue
493 * @return number of events in the queue
495 int queue_count(const struct event_queue
*q
)
497 int oldlevel
= set_irq_level(HIGHEST_IRQ_LEVEL
);
505 if (q
->read
<= q
->write
)
506 result
= q
->write
- q
->read
;
508 result
= QUEUE_LENGTH
- (q
->read
- q
->write
);
515 set_irq_level(oldlevel
);
520 int queue_broadcast(long id
, intptr_t data
)
524 for(i
= 0;i
< num_queues
;i
++)
526 queue_post(all_queues
[i
], id
, data
);
532 /****************************************************************************
534 ****************************************************************************/
535 #if CONFIG_CPU == SH7034
536 void tick_start(unsigned int interval_in_ms
)
540 count
= CPU_FREQ
* interval_in_ms
/ 1000 / 8;
544 panicf("Error! The tick interval is too long (%d ms)\n",
549 /* We are using timer 0 */
551 TSTR
&= ~0x01; /* Stop the timer */
552 TSNC
&= ~0x01; /* No synchronization */
553 TMDR
&= ~0x01; /* Operate normally */
555 TCNT0
= 0; /* Start counting at 0 */
556 GRA0
= (unsigned short)(count
- 1);
557 TCR0
= 0x23; /* Clear at GRA match, sysclock/8 */
559 /* Enable interrupt on level 1 */
560 IPRC
= (IPRC
& ~0x00f0) | 0x0010;
563 TIER0
= 0xf9; /* Enable GRA match interrupt */
565 TSTR
|= 0x01; /* Start timer 1 */
568 void IMIA0(void) __attribute__ ((interrupt_handler
));
573 /* Run through the list of tick tasks */
574 for(i
= 0;i
< MAX_NUM_TICK_TASKS
;i
++)
586 #elif defined(CPU_COLDFIRE)
587 void tick_start(unsigned int interval_in_ms
)
592 count
= CPU_FREQ
/2 * interval_in_ms
/ 1000 / 16;
596 panicf("Error! The tick interval is too long (%d ms)\n",
601 prescale
= cpu_frequency
/ CPU_FREQ
;
602 /* Note: The prescaler is later adjusted on-the-fly on CPU frequency
603 changes within timer.c */
605 /* We are using timer 0 */
607 TRR0
= (unsigned short)(count
- 1); /* The reference count */
608 TCN0
= 0; /* reset the timer */
609 TMR0
= 0x001d | ((unsigned short)(prescale
- 1) << 8);
610 /* restart, CLK/16, enabled, prescaler */
612 TER0
= 0xff; /* Clear all events */
614 ICR1
= 0x8c; /* Interrupt on level 3.0 */
618 void TIMER0(void) __attribute__ ((interrupt_handler
));
623 /* Run through the list of tick tasks */
624 for(i
= 0;i
< MAX_NUM_TICK_TASKS
;i
++)
634 TER0
= 0xff; /* Clear all events */
637 #elif defined(CPU_PP)
644 TIMER1_VAL
; /* Read value to ack IRQ */
645 /* Run through the list of tick tasks (using main core) */
646 if (CURRENT_CORE
== CPU
)
648 for (i
= 0;i
< MAX_NUM_TICK_TASKS
;i
++)
661 void tick_start(unsigned int interval_in_ms
)
664 if(CURRENT_CORE
== CPU
)
669 TIMER1_CFG
= 0xc0000000 | (interval_in_ms
*1000 - 1);
670 /* unmask interrupt source */
671 CPU_INT_EN
= TIMER1_MASK
;
673 COP_INT_EN
= TIMER1_MASK
;
676 /* We don't enable interrupts in the bootloader */
677 (void)interval_in_ms
;
681 #elif CONFIG_CPU == PNX0101
683 void timer_handler(void)
687 /* Run through the list of tick tasks */
688 for(i
= 0;i
< MAX_NUM_TICK_TASKS
;i
++)
699 void tick_start(unsigned int interval_in_ms
)
701 TIMER0
.ctrl
&= ~0x80; /* Disable the counter */
702 TIMER0
.ctrl
|= 0x40; /* Reload after counting down to zero */
703 TIMER0
.load
= 3000000 * interval_in_ms
/ 1000;
704 TIMER0
.ctrl
&= ~0xc; /* No prescaler */
705 TIMER0
.clr
= 1; /* Clear the interrupt request */
707 irq_set_int_handler(IRQ_TIMER0
, timer_handler
);
708 irq_enable_int(IRQ_TIMER0
);
710 TIMER0
.ctrl
|= 0x80; /* Enable the counter */
712 #elif CONFIG_CPU == S3C2440
713 void tick_start(unsigned int interval_in_ms
)
715 TCON
&= ~(1 << 20); // stop timer 4
716 // TODO: this constant depends on dividers settings inherited from
717 // firmware. Set them explicitly somwhere.
718 TCNTB4
= 12193 * interval_in_ms
/ 1000;
719 TCON
|= 1 << 21; // set manual bit
720 TCON
&= ~(1 << 21); // reset manual bit
721 TCON
|= 1 << 22; //interval mode
722 TCON
|= (1 << 20); // start timer 4
724 INTMOD
&= ~(1 << 14); // timer 4 to IRQ mode
725 INTMSK
&= ~(1 << 14); // timer 4 unmask interrupts
730 /* Run through the list of tick tasks */
731 for(i
= 0; i
< MAX_NUM_TICK_TASKS
; i
++)
741 /* following needs to be fixed. */
742 /*wake_up_thread();*/
746 int tick_add_task(void (*f
)(void))
749 int oldlevel
= set_irq_level(HIGHEST_IRQ_LEVEL
);
751 /* Add a task if there is room */
752 for(i
= 0;i
< MAX_NUM_TICK_TASKS
;i
++)
754 if(tick_funcs
[i
] == NULL
)
757 set_irq_level(oldlevel
);
761 set_irq_level(oldlevel
);
762 panicf("Error! tick_add_task(): out of tasks");
766 int tick_remove_task(void (*f
)(void))
769 int oldlevel
= set_irq_level(HIGHEST_IRQ_LEVEL
);
771 /* Remove a task if it is there */
772 for(i
= 0;i
< MAX_NUM_TICK_TASKS
;i
++)
774 if(tick_funcs
[i
] == f
)
776 tick_funcs
[i
] = NULL
;
777 set_irq_level(oldlevel
);
782 set_irq_level(oldlevel
);
788 * Simulator versions in uisimulator/SIMVER/
791 /****************************************************************************
792 * Simple mutex functions
793 ****************************************************************************/
794 void mutex_init(struct mutex
*m
)
800 void mutex_lock(struct mutex
*m
)
802 if (test_and_set(&m
->locked
, 1))
804 /* Wait until the lock is open... */
805 block_thread(&m
->thread
);
809 void mutex_unlock(struct mutex
*m
)
813 if (m
->thread
== NULL
)
816 wakeup_thread(&m
->thread
);
821 void spinlock_lock(struct mutex
*m
)
823 while (test_and_set(&m
->locked
, 1))
825 /* wait until the lock is open... */
826 switch_thread(true, NULL
);
830 void spinlock_unlock(struct mutex
*m
)
835 #endif /* ndef SIMULATOR */