summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
Diffstat (limited to 'firmware')
-rw-r--r--firmware/drivers/audio/uda1380.c4
-rw-r--r--firmware/drivers/button.c4
-rw-r--r--firmware/drivers/rtc/rtc_pcf50606.c8
-rw-r--r--firmware/kernel.c96
-rw-r--r--firmware/mp3_playback.c4
-rw-r--r--firmware/mpeg.c12
-rw-r--r--firmware/rolo.c6
-rw-r--r--firmware/target/arm/i2c-pp.c12
-rw-r--r--firmware/target/arm/ipod/backlight-nano_video.c8
-rw-r--r--firmware/target/arm/ipod/video/lcd-video.c10
-rw-r--r--firmware/target/arm/pcm-pp.c16
-rw-r--r--firmware/target/arm/pnx0101/iriver-ifp7xx/power-ifp7xx.c5
-rw-r--r--firmware/target/arm/pnx0101/system-pnx0101.c4
-rw-r--r--firmware/target/arm/s3c2440/gigabeat-fx/pcm-meg-fx.c12
-rw-r--r--firmware/target/arm/s3c2440/gigabeat-fx/timer-meg-fx.c4
-rw-r--r--firmware/target/arm/system-arm.h97
-rw-r--r--firmware/target/arm/tatung/tpj1022/backlight-tpj1022.c8
-rw-r--r--firmware/target/arm/tms320dm320/dsp-dm320.c4
-rw-r--r--firmware/target/arm/tms320dm320/timer-dm320.c4
-rw-r--r--firmware/target/coldfire/iaudio/adc-iaudio.c4
-rw-r--r--firmware/target/coldfire/iaudio/m3/audio-m3.c2
-rw-r--r--firmware/target/coldfire/iaudio/m5/audio-m5.c2
-rw-r--r--firmware/target/coldfire/iaudio/m5/backlight-m5.c8
-rw-r--r--firmware/target/coldfire/iaudio/m5/power-m5.c8
-rw-r--r--firmware/target/coldfire/iaudio/pcf50606-iaudio.c4
-rw-r--r--firmware/target/coldfire/iaudio/x5/audio-x5.c2
-rw-r--r--firmware/target/coldfire/iaudio/x5/backlight-x5.c12
-rw-r--r--firmware/target/coldfire/iaudio/x5/ds2411-x5.c4
-rw-r--r--firmware/target/coldfire/iaudio/x5/power-x5.c8
-rw-r--r--firmware/target/coldfire/iriver/audio-iriver.c2
-rw-r--r--firmware/target/coldfire/iriver/h100/adc-h100.c4
-rw-r--r--firmware/target/coldfire/iriver/h100/power-h100.c3
-rw-r--r--firmware/target/coldfire/iriver/h100/spdif-h100.c2
-rw-r--r--firmware/target/coldfire/iriver/h300/adc-h300.c4
-rw-r--r--firmware/target/coldfire/iriver/h300/backlight-h300.c4
-rw-r--r--firmware/target/coldfire/iriver/h300/power-h300.c3
-rw-r--r--firmware/target/coldfire/iriver/lcd-remote-iriver.c4
-rw-r--r--firmware/target/coldfire/pcm-coldfire.c4
-rw-r--r--firmware/target/coldfire/system-coldfire.c2
-rw-r--r--firmware/target/coldfire/system-target.h49
-rw-r--r--firmware/target/sh/archos/fm_v2/power-fm_v2.c5
-rw-r--r--firmware/target/sh/archos/ondio/power-ondio.c5
-rw-r--r--firmware/target/sh/archos/player/power-player.c5
-rw-r--r--firmware/target/sh/archos/recorder/power-recorder.c5
-rw-r--r--firmware/target/sh/system-sh.c2
-rw-r--r--firmware/target/sh/system-target.h20
-rw-r--r--firmware/test/i2c/main.c2
-rw-r--r--firmware/test/kernel/main.c2
-rw-r--r--firmware/thread.c82
-rw-r--r--firmware/usb.c4
50 files changed, 337 insertions, 248 deletions
diff --git a/firmware/drivers/audio/uda1380.c b/firmware/drivers/audio/uda1380.c
index ce69ef6b80..f6a7c730cb 100644
--- a/firmware/drivers/audio/uda1380.c
+++ b/firmware/drivers/audio/uda1380.c
@@ -203,10 +203,10 @@ void audiohw_enable_output(bool enable)
203static void reset(void) 203static void reset(void)
204{ 204{
205#ifdef IRIVER_H300_SERIES 205#ifdef IRIVER_H300_SERIES
206 int mask = set_irq_level(HIGHEST_IRQ_LEVEL); 206 int mask = disable_irq_save();
207 pcf50606_write(0x3b, 0x00); /* GPOOD2 high Z */ 207 pcf50606_write(0x3b, 0x00); /* GPOOD2 high Z */
208 pcf50606_write(0x3b, 0x07); /* GPOOD2 low */ 208 pcf50606_write(0x3b, 0x07); /* GPOOD2 low */
209 set_irq_level(mask); 209 restore_irq(mask);
210#else 210#else
211 /* RESET signal */ 211 /* RESET signal */
212 or_l(1<<29, &GPIO_OUT); 212 or_l(1<<29, &GPIO_OUT);
diff --git a/firmware/drivers/button.c b/firmware/drivers/button.c
index b9473bec24..d38306b3ca 100644
--- a/firmware/drivers/button.c
+++ b/firmware/drivers/button.c
@@ -465,10 +465,10 @@ void button_set_flip(bool flip)
465 if (flip != flipped) /* not the current setting */ 465 if (flip != flipped) /* not the current setting */
466 { 466 {
467 /* avoid race condition with the button_tick() */ 467 /* avoid race condition with the button_tick() */
468 int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); 468 int oldlevel = disable_irq_save();
469 lastbtn = button_flip(lastbtn); 469 lastbtn = button_flip(lastbtn);
470 flipped = flip; 470 flipped = flip;
471 set_irq_level(oldlevel); 471 restore_irq(oldlevel);
472 } 472 }
473} 473}
474#endif /* HAVE_LCD_BITMAP */ 474#endif /* HAVE_LCD_BITMAP */
diff --git a/firmware/drivers/rtc/rtc_pcf50606.c b/firmware/drivers/rtc/rtc_pcf50606.c
index 25b0c704c0..9b4de44d3f 100644
--- a/firmware/drivers/rtc/rtc_pcf50606.c
+++ b/firmware/drivers/rtc/rtc_pcf50606.c
@@ -30,21 +30,21 @@ void rtc_init(void)
30 30
31int rtc_read_datetime(unsigned char* buf) { 31int rtc_read_datetime(unsigned char* buf) {
32 int rc; 32 int rc;
33 int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); 33 int oldlevel = disable_irq_save();
34 34
35 rc = pcf50606_read_multiple(0x0a, buf, 7); 35 rc = pcf50606_read_multiple(0x0a, buf, 7);
36 36
37 set_irq_level(oldlevel); 37 restore_irq(oldlevel);
38 return rc; 38 return rc;
39} 39}
40 40
41int rtc_write_datetime(unsigned char* buf) { 41int rtc_write_datetime(unsigned char* buf) {
42 int rc; 42 int rc;
43 int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); 43 int oldlevel = disable_irq_save();
44 44
45 rc = pcf50606_write_multiple(0x0a, buf, 7); 45 rc = pcf50606_write_multiple(0x0a, buf, 7);
46 46
47 set_irq_level(oldlevel); 47 restore_irq(oldlevel);
48 48
49 return rc; 49 return rc;
50} 50}
diff --git a/firmware/kernel.c b/firmware/kernel.c
index 47c0d58a95..be0cfb56a4 100644
--- a/firmware/kernel.c
+++ b/firmware/kernel.c
@@ -270,7 +270,7 @@ void tick_start(unsigned int interval_in_ms)
270int tick_add_task(void (*f)(void)) 270int tick_add_task(void (*f)(void))
271{ 271{
272 int i; 272 int i;
273 int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); 273 int oldlevel = disable_irq_save();
274 274
275 /* Add a task if there is room */ 275 /* Add a task if there is room */
276 for(i = 0;i < MAX_NUM_TICK_TASKS;i++) 276 for(i = 0;i < MAX_NUM_TICK_TASKS;i++)
@@ -278,11 +278,11 @@ int tick_add_task(void (*f)(void))
278 if(tick_funcs[i] == NULL) 278 if(tick_funcs[i] == NULL)
279 { 279 {
280 tick_funcs[i] = f; 280 tick_funcs[i] = f;
281 set_irq_level(oldlevel); 281 restore_irq(oldlevel);
282 return 0; 282 return 0;
283 } 283 }
284 } 284 }
285 set_irq_level(oldlevel); 285 restore_irq(oldlevel);
286 panicf("Error! tick_add_task(): out of tasks"); 286 panicf("Error! tick_add_task(): out of tasks");
287 return -1; 287 return -1;
288} 288}
@@ -290,7 +290,7 @@ int tick_add_task(void (*f)(void))
290int tick_remove_task(void (*f)(void)) 290int tick_remove_task(void (*f)(void))
291{ 291{
292 int i; 292 int i;
293 int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); 293 int oldlevel = disable_irq_save();
294 294
295 /* Remove a task if it is there */ 295 /* Remove a task if it is there */
296 for(i = 0;i < MAX_NUM_TICK_TASKS;i++) 296 for(i = 0;i < MAX_NUM_TICK_TASKS;i++)
@@ -298,12 +298,12 @@ int tick_remove_task(void (*f)(void))
298 if(tick_funcs[i] == f) 298 if(tick_funcs[i] == f)
299 { 299 {
300 tick_funcs[i] = NULL; 300 tick_funcs[i] = NULL;
301 set_irq_level(oldlevel); 301 restore_irq(oldlevel);
302 return 0; 302 return 0;
303 } 303 }
304 } 304 }
305 305
306 set_irq_level(oldlevel); 306 restore_irq(oldlevel);
307 return -1; 307 return -1;
308} 308}
309 309
@@ -341,7 +341,7 @@ static void timeout_tick(void)
341/* Cancels a timeout callback - can be called from the ISR */ 341/* Cancels a timeout callback - can be called from the ISR */
342void timeout_cancel(struct timeout *tmo) 342void timeout_cancel(struct timeout *tmo)
343{ 343{
344 int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); 344 int oldlevel = disable_irq_save();
345 345
346 if (tmo_list != NULL) 346 if (tmo_list != NULL)
347 { 347 {
@@ -368,7 +368,7 @@ void timeout_cancel(struct timeout *tmo)
368 /* not in list or tmo == NULL */ 368 /* not in list or tmo == NULL */
369 } 369 }
370 370
371 set_irq_level(oldlevel); 371 restore_irq(oldlevel);
372} 372}
373 373
374/* Adds a timeout callback - calling with an active timeout resets the 374/* Adds a timeout callback - calling with an active timeout resets the
@@ -382,7 +382,7 @@ void timeout_register(struct timeout *tmo, timeout_cb_type callback,
382 if (tmo == NULL) 382 if (tmo == NULL)
383 return; 383 return;
384 384
385 oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); 385 oldlevel = disable_irq_save();
386 386
387 /* see if this one is already registered */ 387 /* see if this one is already registered */
388 curr = tmo_list; 388 curr = tmo_list;
@@ -404,7 +404,7 @@ void timeout_register(struct timeout *tmo, timeout_cb_type callback,
404 tmo->data = data; 404 tmo->data = data;
405 *(long *)&tmo->expires = current_tick + ticks; 405 *(long *)&tmo->expires = current_tick + ticks;
406 406
407 set_irq_level(oldlevel); 407 restore_irq(oldlevel);
408} 408}
409 409
410#endif /* INCLUDE_TIMEOUT_API */ 410#endif /* INCLUDE_TIMEOUT_API */
@@ -433,7 +433,7 @@ void sleep(int ticks)
433 while (TIME_BEFORE(USEC_TIMER, stop)) 433 while (TIME_BEFORE(USEC_TIMER, stop))
434 switch_thread(); 434 switch_thread();
435#else 435#else
436 set_irq_level(HIGHEST_IRQ_LEVEL); 436 disable_irq();
437 sleep_thread(ticks); 437 sleep_thread(ticks);
438 switch_thread(); 438 switch_thread();
439#endif 439#endif
@@ -537,7 +537,7 @@ void queue_enable_queue_send(struct event_queue *q,
537 struct queue_sender_list *send, 537 struct queue_sender_list *send,
538 struct thread_entry *owner) 538 struct thread_entry *owner)
539{ 539{
540 int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); 540 int oldlevel = disable_irq_save();
541 corelock_lock(&q->cl); 541 corelock_lock(&q->cl);
542 542
543 if(send != NULL && q->send == NULL) 543 if(send != NULL && q->send == NULL)
@@ -554,7 +554,7 @@ void queue_enable_queue_send(struct event_queue *q,
554 } 554 }
555 555
556 corelock_unlock(&q->cl); 556 corelock_unlock(&q->cl);
557 set_irq_level(oldlevel); 557 restore_irq(oldlevel);
558 558
559 (void)owner; 559 (void)owner;
560} 560}
@@ -618,7 +618,7 @@ static inline void queue_do_fetch_sender(struct queue_sender_list *send,
618/* Queue must not be available for use during this call */ 618/* Queue must not be available for use during this call */
619void queue_init(struct event_queue *q, bool register_queue) 619void queue_init(struct event_queue *q, bool register_queue)
620{ 620{
621 int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); 621 int oldlevel = disable_irq_save();
622 622
623 if(register_queue) 623 if(register_queue)
624 { 624 {
@@ -645,7 +645,7 @@ void queue_init(struct event_queue *q, bool register_queue)
645 corelock_unlock(&all_queues.cl); 645 corelock_unlock(&all_queues.cl);
646 } 646 }
647 647
648 set_irq_level(oldlevel); 648 restore_irq(oldlevel);
649} 649}
650 650
651/* Queue must not be available for use during this call */ 651/* Queue must not be available for use during this call */
@@ -654,7 +654,7 @@ void queue_delete(struct event_queue *q)
654 int oldlevel; 654 int oldlevel;
655 int i; 655 int i;
656 656
657 oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); 657 oldlevel = disable_irq_save();
658 corelock_lock(&all_queues.cl); 658 corelock_lock(&all_queues.cl);
659 corelock_lock(&q->cl); 659 corelock_lock(&q->cl);
660 660
@@ -697,7 +697,7 @@ void queue_delete(struct event_queue *q)
697 q->write = 0; 697 q->write = 0;
698 698
699 corelock_unlock(&q->cl); 699 corelock_unlock(&q->cl);
700 set_irq_level(oldlevel); 700 restore_irq(oldlevel);
701} 701}
702 702
703/* NOTE: multiple threads waiting on a queue head cannot have a well- 703/* NOTE: multiple threads waiting on a queue head cannot have a well-
@@ -714,7 +714,7 @@ void queue_wait(struct event_queue *q, struct queue_event *ev)
714 "queue_wait->wrong thread\n"); 714 "queue_wait->wrong thread\n");
715#endif 715#endif
716 716
717 oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); 717 oldlevel = disable_irq_save();
718 corelock_lock(&q->cl); 718 corelock_lock(&q->cl);
719 719
720 /* auto-reply */ 720 /* auto-reply */
@@ -734,7 +734,7 @@ void queue_wait(struct event_queue *q, struct queue_event *ev)
734 corelock_unlock(&q->cl); 734 corelock_unlock(&q->cl);
735 switch_thread(); 735 switch_thread();
736 736
737 oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); 737 oldlevel = disable_irq_save();
738 corelock_lock(&q->cl); 738 corelock_lock(&q->cl);
739 } 739 }
740 /* A message that woke us could now be gone */ 740 /* A message that woke us could now be gone */
@@ -748,7 +748,7 @@ void queue_wait(struct event_queue *q, struct queue_event *ev)
748 queue_do_fetch_sender(q->send, rd); 748 queue_do_fetch_sender(q->send, rd);
749 749
750 corelock_unlock(&q->cl); 750 corelock_unlock(&q->cl);
751 set_irq_level(oldlevel); 751 restore_irq(oldlevel);
752} 752}
753 753
754void queue_wait_w_tmo(struct event_queue *q, struct queue_event *ev, int ticks) 754void queue_wait_w_tmo(struct event_queue *q, struct queue_event *ev, int ticks)
@@ -761,7 +761,7 @@ void queue_wait_w_tmo(struct event_queue *q, struct queue_event *ev, int ticks)
761 "queue_wait_w_tmo->wrong thread\n"); 761 "queue_wait_w_tmo->wrong thread\n");
762#endif 762#endif
763 763
764 oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); 764 oldlevel = disable_irq_save();
765 corelock_lock(&q->cl); 765 corelock_lock(&q->cl);
766 766
767 /* Auto-reply */ 767 /* Auto-reply */
@@ -779,7 +779,7 @@ void queue_wait_w_tmo(struct event_queue *q, struct queue_event *ev, int ticks)
779 779
780 switch_thread(); 780 switch_thread();
781 781
782 oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); 782 oldlevel = disable_irq_save();
783 corelock_lock(&q->cl); 783 corelock_lock(&q->cl);
784 } 784 }
785 785
@@ -798,7 +798,7 @@ void queue_wait_w_tmo(struct event_queue *q, struct queue_event *ev, int ticks)
798 } 798 }
799 799
800 corelock_unlock(&q->cl); 800 corelock_unlock(&q->cl);
801 set_irq_level(oldlevel); 801 restore_irq(oldlevel);
802} 802}
803 803
804void queue_post(struct event_queue *q, long id, intptr_t data) 804void queue_post(struct event_queue *q, long id, intptr_t data)
@@ -806,7 +806,7 @@ void queue_post(struct event_queue *q, long id, intptr_t data)
806 int oldlevel; 806 int oldlevel;
807 unsigned int wr; 807 unsigned int wr;
808 808
809 oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); 809 oldlevel = disable_irq_save();
810 corelock_lock(&q->cl); 810 corelock_lock(&q->cl);
811 811
812 wr = q->write++ & QUEUE_LENGTH_MASK; 812 wr = q->write++ & QUEUE_LENGTH_MASK;
@@ -821,7 +821,7 @@ void queue_post(struct event_queue *q, long id, intptr_t data)
821 wakeup_thread(&q->queue); 821 wakeup_thread(&q->queue);
822 822
823 corelock_unlock(&q->cl); 823 corelock_unlock(&q->cl);
824 set_irq_level(oldlevel); 824 restore_irq(oldlevel);
825} 825}
826 826
827#ifdef HAVE_EXTENDED_MESSAGING_AND_NAME 827#ifdef HAVE_EXTENDED_MESSAGING_AND_NAME
@@ -832,7 +832,7 @@ intptr_t queue_send(struct event_queue *q, long id, intptr_t data)
832 int oldlevel; 832 int oldlevel;
833 unsigned int wr; 833 unsigned int wr;
834 834
835 oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); 835 oldlevel = disable_irq_save();
836 corelock_lock(&q->cl); 836 corelock_lock(&q->cl);
837 837
838 wr = q->write++ & QUEUE_LENGTH_MASK; 838 wr = q->write++ & QUEUE_LENGTH_MASK;
@@ -875,7 +875,7 @@ intptr_t queue_send(struct event_queue *q, long id, intptr_t data)
875 wakeup_thread(&q->queue); 875 wakeup_thread(&q->queue);
876 876
877 corelock_unlock(&q->cl); 877 corelock_unlock(&q->cl);
878 set_irq_level(oldlevel); 878 restore_irq(oldlevel);
879 879
880 return 0; 880 return 0;
881} 881}
@@ -887,7 +887,7 @@ bool queue_in_queue_send(struct event_queue *q)
887 bool in_send; 887 bool in_send;
888 888
889#if NUM_CORES > 1 889#if NUM_CORES > 1
890 int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); 890 int oldlevel = disable_irq_save();
891 corelock_lock(&q->cl); 891 corelock_lock(&q->cl);
892#endif 892#endif
893 893
@@ -895,7 +895,7 @@ bool queue_in_queue_send(struct event_queue *q)
895 895
896#if NUM_CORES > 1 896#if NUM_CORES > 1
897 corelock_unlock(&q->cl); 897 corelock_unlock(&q->cl);
898 set_irq_level(oldlevel); 898 restore_irq(oldlevel);
899#endif 899#endif
900 900
901 return in_send; 901 return in_send;
@@ -907,7 +907,7 @@ void queue_reply(struct event_queue *q, intptr_t retval)
907{ 907{
908 if(q->send && q->send->curr_sender) 908 if(q->send && q->send->curr_sender)
909 { 909 {
910 int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); 910 int oldlevel = disable_irq_save();
911 corelock_lock(&q->cl); 911 corelock_lock(&q->cl);
912 /* Double-check locking */ 912 /* Double-check locking */
913 IF_COP( if(q->send && q->send->curr_sender) ) 913 IF_COP( if(q->send && q->send->curr_sender) )
@@ -916,7 +916,7 @@ void queue_reply(struct event_queue *q, intptr_t retval)
916 } 916 }
917 917
918 corelock_unlock(&q->cl); 918 corelock_unlock(&q->cl);
919 set_irq_level(oldlevel); 919 restore_irq(oldlevel);
920 } 920 }
921} 921}
922 922
@@ -927,7 +927,7 @@ bool queue_peek(struct event_queue *q, struct queue_event *ev)
927 927
928 bool have_msg = false; 928 bool have_msg = false;
929 929
930 int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); 930 int oldlevel = disable_irq_save();
931 corelock_lock(&q->cl); 931 corelock_lock(&q->cl);
932 932
933 if(q->read != q->write) 933 if(q->read != q->write)
@@ -937,7 +937,7 @@ bool queue_peek(struct event_queue *q, struct queue_event *ev)
937 } 937 }
938 938
939 corelock_unlock(&q->cl); 939 corelock_unlock(&q->cl);
940 set_irq_level(oldlevel); 940 restore_irq(oldlevel);
941 941
942 return have_msg; 942 return have_msg;
943} 943}
@@ -956,7 +956,7 @@ void queue_clear(struct event_queue* q)
956{ 956{
957 int oldlevel; 957 int oldlevel;
958 958
959 oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); 959 oldlevel = disable_irq_save();
960 corelock_lock(&q->cl); 960 corelock_lock(&q->cl);
961 961
962 /* Release all threads waiting in the queue for a reply - 962 /* Release all threads waiting in the queue for a reply -
@@ -967,14 +967,14 @@ void queue_clear(struct event_queue* q)
967 q->write = 0; 967 q->write = 0;
968 968
969 corelock_unlock(&q->cl); 969 corelock_unlock(&q->cl);
970 set_irq_level(oldlevel); 970 restore_irq(oldlevel);
971} 971}
972 972
973void queue_remove_from_head(struct event_queue *q, long id) 973void queue_remove_from_head(struct event_queue *q, long id)
974{ 974{
975 int oldlevel; 975 int oldlevel;
976 976
977 oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); 977 oldlevel = disable_irq_save();
978 corelock_lock(&q->cl); 978 corelock_lock(&q->cl);
979 979
980 while(q->read != q->write) 980 while(q->read != q->write)
@@ -993,7 +993,7 @@ void queue_remove_from_head(struct event_queue *q, long id)
993 } 993 }
994 994
995 corelock_unlock(&q->cl); 995 corelock_unlock(&q->cl);
996 set_irq_level(oldlevel); 996 restore_irq(oldlevel);
997} 997}
998 998
999/** 999/**
@@ -1012,7 +1012,7 @@ int queue_broadcast(long id, intptr_t data)
1012 int i; 1012 int i;
1013 1013
1014#if NUM_CORES > 1 1014#if NUM_CORES > 1
1015 int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); 1015 int oldlevel = disable_irq_save();
1016 corelock_lock(&all_queues.cl); 1016 corelock_lock(&all_queues.cl);
1017#endif 1017#endif
1018 1018
@@ -1023,7 +1023,7 @@ int queue_broadcast(long id, intptr_t data)
1023 1023
1024#if NUM_CORES > 1 1024#if NUM_CORES > 1
1025 corelock_unlock(&all_queues.cl); 1025 corelock_unlock(&all_queues.cl);
1026 set_irq_level(oldlevel); 1026 restore_irq(oldlevel);
1027#endif 1027#endif
1028 1028
1029 return i; 1029 return i;
@@ -1079,7 +1079,7 @@ void mutex_lock(struct mutex *m)
1079 IF_PRIO( current->blocker = &m->blocker; ) 1079 IF_PRIO( current->blocker = &m->blocker; )
1080 current->bqp = &m->queue; 1080 current->bqp = &m->queue;
1081 1081
1082 set_irq_level(HIGHEST_IRQ_LEVEL); 1082 disable_irq();
1083 block_thread(current); 1083 block_thread(current);
1084 1084
1085 corelock_unlock(&m->cl); 1085 corelock_unlock(&m->cl);
@@ -1118,13 +1118,13 @@ void mutex_unlock(struct mutex *m)
1118 } 1118 }
1119 else 1119 else
1120 { 1120 {
1121 const int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); 1121 const int oldlevel = disable_irq_save();
1122 /* Tranfer of owning thread is handled in the wakeup protocol 1122 /* Tranfer of owning thread is handled in the wakeup protocol
1123 * if priorities are enabled otherwise just set it from the 1123 * if priorities are enabled otherwise just set it from the
1124 * queue head. */ 1124 * queue head. */
1125 IFN_PRIO( MUTEX_SET_THREAD(m, m->queue); ) 1125 IFN_PRIO( MUTEX_SET_THREAD(m, m->queue); )
1126 IF_PRIO( unsigned int result = ) wakeup_thread(&m->queue); 1126 IF_PRIO( unsigned int result = ) wakeup_thread(&m->queue);
1127 set_irq_level(oldlevel); 1127 restore_irq(oldlevel);
1128 1128
1129 corelock_unlock(&m->cl); 1129 corelock_unlock(&m->cl);
1130 1130
@@ -1219,7 +1219,7 @@ void semaphore_wait(struct semaphore *s)
1219 IF_COP( current->obj_cl = &s->cl; ) 1219 IF_COP( current->obj_cl = &s->cl; )
1220 current->bqp = &s->queue; 1220 current->bqp = &s->queue;
1221 1221
1222 set_irq_level(HIGHEST_IRQ_LEVEL); 1222 disable_irq();
1223 block_thread(current); 1223 block_thread(current);
1224 1224
1225 corelock_unlock(&s->cl); 1225 corelock_unlock(&s->cl);
@@ -1239,9 +1239,9 @@ void semaphore_release(struct semaphore *s)
1239 /* there should be threads in this queue */ 1239 /* there should be threads in this queue */
1240 KERNEL_ASSERT(s->queue != NULL, "semaphore->wakeup\n"); 1240 KERNEL_ASSERT(s->queue != NULL, "semaphore->wakeup\n");
1241 /* a thread was queued - wake it up */ 1241 /* a thread was queued - wake it up */
1242 int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); 1242 int oldlevel = disable_irq_save();
1243 IF_PRIO( result = ) wakeup_thread(&s->queue); 1243 IF_PRIO( result = ) wakeup_thread(&s->queue);
1244 set_irq_level(oldlevel); 1244 restore_irq(oldlevel);
1245 } 1245 }
1246 1246
1247 corelock_unlock(&s->cl); 1247 corelock_unlock(&s->cl);
@@ -1298,7 +1298,7 @@ void event_wait(struct event *e, unsigned int for_state)
1298 IF_COP( current->obj_cl = &e->cl; ) 1298 IF_COP( current->obj_cl = &e->cl; )
1299 current->bqp = &e->queues[for_state]; 1299 current->bqp = &e->queues[for_state];
1300 1300
1301 set_irq_level(HIGHEST_IRQ_LEVEL); 1301 disable_irq();
1302 block_thread(current); 1302 block_thread(current);
1303 1303
1304 corelock_unlock(&e->cl); 1304 corelock_unlock(&e->cl);
@@ -1323,7 +1323,7 @@ void event_set_state(struct event *e, unsigned int state)
1323 1323
1324 IF_PRIO( result = THREAD_OK; ) 1324 IF_PRIO( result = THREAD_OK; )
1325 1325
1326 oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); 1326 oldlevel = disable_irq_save();
1327 1327
1328 if(state == STATE_SIGNALED) 1328 if(state == STATE_SIGNALED)
1329 { 1329 {
@@ -1357,7 +1357,7 @@ void event_set_state(struct event *e, unsigned int state)
1357 thread_queue_wake(&e->queues[STATE_NONSIGNALED]); 1357 thread_queue_wake(&e->queues[STATE_NONSIGNALED]);
1358 } 1358 }
1359 1359
1360 set_irq_level(oldlevel); 1360 restore_irq(oldlevel);
1361 1361
1362 corelock_unlock(&e->cl); 1362 corelock_unlock(&e->cl);
1363 1363
diff --git a/firmware/mp3_playback.c b/firmware/mp3_playback.c
index b2b7205318..ed71be290c 100644
--- a/firmware/mp3_playback.c
+++ b/firmware/mp3_playback.c
@@ -134,7 +134,7 @@ static void postpone_dma_tick(void)
134#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) 134#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
135void demand_irq_enable(bool on) 135void demand_irq_enable(bool on)
136{ 136{
137 int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); 137 int oldlevel = disable_irq_save();
138 138
139 if(on) 139 if(on)
140 { 140 {
@@ -144,7 +144,7 @@ void demand_irq_enable(bool on)
144 else 144 else
145 IPRA &= 0xfff0; 145 IPRA &= 0xfff0;
146 146
147 set_irq_level(oldlevel); 147 restore_irq(oldlevel);
148} 148}
149#endif /* #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */ 149#endif /* #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */
150 150
diff --git a/firmware/mpeg.c b/firmware/mpeg.c
index 273f630799..11cbcdcb68 100644
--- a/firmware/mpeg.c
+++ b/firmware/mpeg.c
@@ -1767,9 +1767,9 @@ static void mpeg_thread(void)
1767 DEBUGF("New audiobuf_read address: %x (%x)\n", 1767 DEBUGF("New audiobuf_read address: %x (%x)\n",
1768 audiobuf+audiobuf_read, audiobuf_read); 1768 audiobuf+audiobuf_read, audiobuf_read);
1769 1769
1770 level = set_irq_level(HIGHEST_IRQ_LEVEL); 1770 level = disable_irq_save();
1771 num_rec_bytes = get_unsaved_space(); 1771 num_rec_bytes = get_unsaved_space();
1772 set_irq_level(level); 1772 restore_irq(level);
1773 } 1773 }
1774 else 1774 else
1775 { 1775 {
@@ -1860,11 +1860,11 @@ static void mpeg_thread(void)
1860 pause_start_time = record_start_time; 1860 pause_start_time = record_start_time;
1861 1861
1862 /* capture all values at one point */ 1862 /* capture all values at one point */
1863 level = set_irq_level(HIGHEST_IRQ_LEVEL); 1863 level = disable_irq_save();
1864 save_endpos = audiobuf_write; 1864 save_endpos = audiobuf_write;
1865 last_rec_bytes = num_rec_bytes; 1865 last_rec_bytes = num_rec_bytes;
1866 num_rec_bytes = 0; 1866 num_rec_bytes = 0;
1867 set_irq_level(level); 1867 restore_irq(level);
1868 1868
1869 if (amount_to_save >= 1800) 1869 if (amount_to_save >= 1800)
1870 { 1870 {
@@ -1883,9 +1883,9 @@ static void mpeg_thread(void)
1883 save_endpos -= audiobuflen; 1883 save_endpos -= audiobuflen;
1884 1884
1885 last_rec_bytes += offset - 1800; 1885 last_rec_bytes += offset - 1800;
1886 level = set_irq_level(HIGHEST_IRQ_LEVEL); 1886 level = disable_irq_save();
1887 num_rec_bytes += 1800 - offset; 1887 num_rec_bytes += 1800 - offset;
1888 set_irq_level(level); 1888 restore_irq(level);
1889 } 1889 }
1890 1890
1891 saving_status = NEW_FILE; 1891 saving_status = NEW_FILE;
diff --git a/firmware/rolo.c b/firmware/rolo.c
index eac45e10ce..30eba91316 100644
--- a/firmware/rolo.c
+++ b/firmware/rolo.c
@@ -271,7 +271,11 @@ int rolo_load(const char* filename)
271#endif 271#endif
272 adc_close(); 272 adc_close();
273 273
274 set_irq_level(HIGHEST_IRQ_LEVEL); 274#ifdef CPU_ARM
275 disable_fiq();
276#endif
277 set_irq_level(DISABLE_INTERRUPTS);
278
275#elif CONFIG_CPU == SH7034 279#elif CONFIG_CPU == SH7034
276 /* Read file length from header and compare to real file length */ 280 /* Read file length from header and compare to real file length */
277 lseek(fd, FIRMWARE_OFFSET_FILE_LENGTH, SEEK_SET); 281 lseek(fd, FIRMWARE_OFFSET_FILE_LENGTH, SEEK_SET);
diff --git a/firmware/target/arm/i2c-pp.c b/firmware/target/arm/i2c-pp.c
index 1cfbfaeff1..450effc32d 100644
--- a/firmware/target/arm/i2c-pp.c
+++ b/firmware/target/arm/i2c-pp.c
@@ -60,7 +60,7 @@ static int pp_i2c_read_byte(unsigned int addr, unsigned int *data)
60 60
61 { 61 {
62 unsigned int byte; 62 unsigned int byte;
63 int old_irq_level = set_irq_level(HIGHEST_IRQ_LEVEL); 63 int old_irq_level = disable_irq_save();
64 64
65 /* clear top 15 bits, left shift 1, or in 0x1 for a read */ 65 /* clear top 15 bits, left shift 1, or in 0x1 for a read */
66 I2C_ADDR = ((addr << 17) >> 16) | 0x1 ; 66 I2C_ADDR = ((addr << 17) >> 16) | 0x1 ;
@@ -69,19 +69,19 @@ static int pp_i2c_read_byte(unsigned int addr, unsigned int *data)
69 69
70 I2C_CTRL |= I2C_SEND; 70 I2C_CTRL |= I2C_SEND;
71 71
72 set_irq_level(old_irq_level); 72 restore_irq(old_irq_level);
73 if (pp_i2c_wait_not_busy() < 0) 73 if (pp_i2c_wait_not_busy() < 0)
74 { 74 {
75 return -1; 75 return -1;
76 } 76 }
77 old_irq_level = set_irq_level(HIGHEST_IRQ_LEVEL); 77 old_irq_level = disable_irq_save();
78 78
79 byte = I2C_DATA(0); 79 byte = I2C_DATA(0);
80 80
81 if (data) 81 if (data)
82 *data = byte; 82 *data = byte;
83 83
84 set_irq_level(old_irq_level); 84 restore_irq(old_irq_level);
85 } 85 }
86 86
87 return 0; 87 return 0;
@@ -102,7 +102,7 @@ static int pp_i2c_send_bytes(unsigned int addr, unsigned int len, unsigned char
102 } 102 }
103 103
104 { 104 {
105 int old_irq_level = set_irq_level(HIGHEST_IRQ_LEVEL); 105 int old_irq_level = disable_irq_save();
106 106
107 /* clear top 15 bits, left shift 1 */ 107 /* clear top 15 bits, left shift 1 */
108 I2C_ADDR = (addr << 17) >> 16; 108 I2C_ADDR = (addr << 17) >> 16;
@@ -118,7 +118,7 @@ static int pp_i2c_send_bytes(unsigned int addr, unsigned int len, unsigned char
118 118
119 I2C_CTRL |= I2C_SEND; 119 I2C_CTRL |= I2C_SEND;
120 120
121 set_irq_level(old_irq_level); 121 restore_irq(old_irq_level);
122 } 122 }
123 123
124 return 0x0; 124 return 0x0;
diff --git a/firmware/target/arm/ipod/backlight-nano_video.c b/firmware/target/arm/ipod/backlight-nano_video.c
index 6d77e2bd03..647bab9ac6 100644
--- a/firmware/target/arm/ipod/backlight-nano_video.c
+++ b/firmware/target/arm/ipod/backlight-nano_video.c
@@ -43,11 +43,11 @@ void _backlight_set_brightness(int val)
43 { 43 {
44 do 44 do
45 { 45 {
46 oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); 46 oldlevel = disable_irq_save();
47 GPIO_CLEAR_BITWISE(GPIOD_OUTPUT_VAL, 0x80); 47 GPIO_CLEAR_BITWISE(GPIOD_OUTPUT_VAL, 0x80);
48 udelay(10); 48 udelay(10);
49 GPIO_SET_BITWISE(GPIOD_OUTPUT_VAL, 0x80); 49 GPIO_SET_BITWISE(GPIOD_OUTPUT_VAL, 0x80);
50 set_irq_level(oldlevel); 50 restore_irq(oldlevel);
51 udelay(10); 51 udelay(10);
52 } 52 }
53 while (++current_dim < val); 53 while (++current_dim < val);
@@ -56,11 +56,11 @@ void _backlight_set_brightness(int val)
56 { 56 {
57 do 57 do
58 { 58 {
59 oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); 59 oldlevel = disable_irq_save();
60 GPIO_CLEAR_BITWISE(GPIOD_OUTPUT_VAL, 0x80); 60 GPIO_CLEAR_BITWISE(GPIOD_OUTPUT_VAL, 0x80);
61 udelay(200); 61 udelay(200);
62 GPIO_SET_BITWISE(GPIOD_OUTPUT_VAL, 0x80); 62 GPIO_SET_BITWISE(GPIOD_OUTPUT_VAL, 0x80);
63 set_irq_level(oldlevel); 63 restore_irq(oldlevel);
64 udelay(10); 64 udelay(10);
65 } 65 }
66 while (--current_dim > val); 66 while (--current_dim > val);
diff --git a/firmware/target/arm/ipod/video/lcd-video.c b/firmware/target/arm/ipod/video/lcd-video.c
index d0c82e905c..0e1b072917 100644
--- a/firmware/target/arm/ipod/video/lcd-video.c
+++ b/firmware/target/arm/ipod/video/lcd-video.c
@@ -110,7 +110,7 @@ static void bcm_setup_rect(unsigned x, unsigned y,
110#ifndef BOOTLOADER 110#ifndef BOOTLOADER
111static void lcd_tick(void) 111static void lcd_tick(void)
112{ 112{
113 /* No set_irq_level - already in interrupt context */ 113 /* No core level interrupt mask - already in interrupt context */
114#if NUM_CORES > 1 114#if NUM_CORES > 1
115 corelock_lock(&lcd_state.cl); 115 corelock_lock(&lcd_state.cl);
116#endif 116#endif
@@ -143,7 +143,7 @@ static void lcd_tick(void)
143 143
144static inline void lcd_block_tick(void) 144static inline void lcd_block_tick(void)
145{ 145{
146 int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); 146 int oldlevel = disable_irq_save();
147 147
148#if NUM_CORES > 1 148#if NUM_CORES > 1
149 corelock_lock(&lcd_state.cl); 149 corelock_lock(&lcd_state.cl);
@@ -152,14 +152,14 @@ static inline void lcd_block_tick(void)
152#else 152#else
153 lcd_state.blocked = true; 153 lcd_state.blocked = true;
154#endif 154#endif
155 set_irq_level(oldlevel); 155 restore_irq(oldlevel);
156} 156}
157 157
158static void lcd_unblock_and_update(void) 158static void lcd_unblock_and_update(void)
159{ 159{
160 unsigned data; 160 unsigned data;
161 bool bcm_is_busy; 161 bool bcm_is_busy;
162 int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); 162 int oldlevel = disable_irq_save();
163 163
164#if NUM_CORES > 1 164#if NUM_CORES > 1
165 corelock_lock(&lcd_state.cl); 165 corelock_lock(&lcd_state.cl);
@@ -184,7 +184,7 @@ static void lcd_unblock_and_update(void)
184#if NUM_CORES > 1 184#if NUM_CORES > 1
185 corelock_unlock(&lcd_state.cl); 185 corelock_unlock(&lcd_state.cl);
186#endif 186#endif
187 set_irq_level(oldlevel); 187 restore_irq(oldlevel);
188} 188}
189 189
190#else /* BOOTLOADER */ 190#else /* BOOTLOADER */
diff --git a/firmware/target/arm/pcm-pp.c b/firmware/target/arm/pcm-pp.c
index 5a9d3b3670..433e6e1e4f 100644
--- a/firmware/target/arm/pcm-pp.c
+++ b/firmware/target/arm/pcm-pp.c
@@ -223,24 +223,24 @@ void fiq_playback(void)
223 will require other measures */ 223 will require other measures */
224void pcm_play_lock(void) 224void pcm_play_lock(void)
225{ 225{
226 int status = set_fiq_status(FIQ_DISABLED); 226 int status = disable_fiq_save();
227 227
228 if (++dma_play_data.locked == 1) { 228 if (++dma_play_data.locked == 1) {
229 IIS_IRQTX_REG &= ~IIS_IRQTX; 229 IIS_IRQTX_REG &= ~IIS_IRQTX;
230 } 230 }
231 231
232 set_fiq_status(status); 232 restore_fiq(status);
233} 233}
234 234
235void pcm_play_unlock(void) 235void pcm_play_unlock(void)
236{ 236{
237 int status = set_fiq_status(FIQ_DISABLED); 237 int status = disable_fiq_save();
238 238
239 if (--dma_play_data.locked == 0 && dma_play_data.state != 0) { 239 if (--dma_play_data.locked == 0 && dma_play_data.state != 0) {
240 IIS_IRQTX_REG |= IIS_IRQTX; 240 IIS_IRQTX_REG |= IIS_IRQTX;
241 } 241 }
242 242
243 set_fiq_status(status); 243 restore_fiq(status);
244} 244}
245 245
246static void play_start_pcm(void) 246static void play_start_pcm(void)
@@ -373,22 +373,22 @@ static struct dma_data dma_rec_data NOCACHEBSS_ATTR =
373 will require other measures */ 373 will require other measures */
374void pcm_rec_lock(void) 374void pcm_rec_lock(void)
375{ 375{
376 int status = set_fiq_status(FIQ_DISABLED); 376 int status = disable_fiq_save();
377 377
378 if (++dma_rec_data.locked == 1) 378 if (++dma_rec_data.locked == 1)
379 IIS_IRQRX_REG &= ~IIS_IRQRX; 379 IIS_IRQRX_REG &= ~IIS_IRQRX;
380 380
381 set_fiq_status(status); 381 restore_fiq(status);
382} 382}
383 383
384void pcm_rec_unlock(void) 384void pcm_rec_unlock(void)
385{ 385{
386 int status = set_fiq_status(FIQ_DISABLED); 386 int status = disable_fiq_save();
387 387
388 if (--dma_rec_data.locked == 0 && dma_rec_data.state != 0) 388 if (--dma_rec_data.locked == 0 && dma_rec_data.state != 0)
389 IIS_IRQRX_REG |= IIS_IRQRX; 389 IIS_IRQRX_REG |= IIS_IRQRX;
390 390
391 set_fiq_status(status); 391 restore_fiq(status);
392} 392}
393 393
394/* NOTE: direct stack use forbidden by GCC stack handling bug for FIQ */ 394/* NOTE: direct stack use forbidden by GCC stack handling bug for FIQ */
diff --git a/firmware/target/arm/pnx0101/iriver-ifp7xx/power-ifp7xx.c b/firmware/target/arm/pnx0101/iriver-ifp7xx/power-ifp7xx.c
index b219244510..4494742bb8 100644
--- a/firmware/target/arm/pnx0101/iriver-ifp7xx/power-ifp7xx.c
+++ b/firmware/target/arm/pnx0101/iriver-ifp7xx/power-ifp7xx.c
@@ -55,11 +55,10 @@ bool ide_powered(void)
55 55
56void power_off(void) 56void power_off(void)
57{ 57{
58 set_irq_level(HIGHEST_IRQ_LEVEL); 58 disable_interrupt(IRQ_FIQ_STATUS);
59 GPIO1_CLR = 1 << 16; 59 GPIO1_CLR = 1 << 16;
60 GPIO2_SET = 1; 60 GPIO2_SET = 1;
61 while(1) 61 while(1);
62 yield();
63} 62}
64 63
65#else 64#else
diff --git a/firmware/target/arm/pnx0101/system-pnx0101.c b/firmware/target/arm/pnx0101/system-pnx0101.c
index da94f397ca..bedcff04ea 100644
--- a/firmware/target/arm/pnx0101/system-pnx0101.c
+++ b/firmware/target/arm/pnx0101/system-pnx0101.c
@@ -113,7 +113,7 @@ static inline void *noncached(void *p)
113static void do_set_mem_timings(void) ICODE_ATTR; 113static void do_set_mem_timings(void) ICODE_ATTR;
114static void do_set_mem_timings(void) 114static void do_set_mem_timings(void)
115{ 115{
116 int old_irq = set_irq_level(HIGHEST_IRQ_LEVEL); 116 int old_irq = disable_irq_save();
117 while ((EMC.status & 3) != 0); 117 while ((EMC.status & 3) != 0);
118 EMC.control = 5; 118 EMC.control = 5;
119 EMCSTATIC0.waitrd = 6; 119 EMCSTATIC0.waitrd = 6;
@@ -130,7 +130,7 @@ static void do_set_mem_timings(void)
130 EMCSTATIC1.config = 0x80081; 130 EMCSTATIC1.config = 0x80081;
131#endif 131#endif
132 EMC.control = 1; 132 EMC.control = 1;
133 set_irq_level(old_irq); 133 restore_irq(old_irq);
134} 134}
135 135
136static void emc_set_mem_timings(void) 136static void emc_set_mem_timings(void)
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/pcm-meg-fx.c b/firmware/target/arm/s3c2440/gigabeat-fx/pcm-meg-fx.c
index 7f25cb6a15..00be543bb6 100644
--- a/firmware/target/arm/s3c2440/gigabeat-fx/pcm-meg-fx.c
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/pcm-meg-fx.c
@@ -66,27 +66,27 @@ static void _pcm_apply_settings(void)
66 66
67void pcm_apply_settings(void) 67void pcm_apply_settings(void)
68{ 68{
69 int oldstatus = set_fiq_status(FIQ_DISABLED); 69 int status = disable_fiq_save();
70 _pcm_apply_settings(); 70 _pcm_apply_settings();
71 set_fiq_status(oldstatus); 71 restore_fiq(status);
72} 72}
73 73
74/* For the locks, DMA interrupt must be disabled because the handler 74/* For the locks, DMA interrupt must be disabled because the handler
75 manipulates INTMSK and the operation is not atomic */ 75 manipulates INTMSK and the operation is not atomic */
76void pcm_play_lock(void) 76void pcm_play_lock(void)
77{ 77{
78 int status = set_fiq_status(FIQ_DISABLED); 78 int status = disable_fiq_save();
79 if (++dma_play_lock.locked == 1) 79 if (++dma_play_lock.locked == 1)
80 INTMSK |= (1<<19); /* Mask the DMA interrupt */ 80 INTMSK |= (1<<19); /* Mask the DMA interrupt */
81 set_fiq_status(status); 81 restore_fiq(status);
82} 82}
83 83
84void pcm_play_unlock(void) 84void pcm_play_unlock(void)
85{ 85{
86 int status = set_fiq_status(FIQ_DISABLED); 86 int status = disable_fiq_save();
87 if (--dma_play_lock.locked == 0) 87 if (--dma_play_lock.locked == 0)
88 INTMSK &= ~dma_play_lock.state; /* Unmask the DMA interrupt if enabled */ 88 INTMSK &= ~dma_play_lock.state; /* Unmask the DMA interrupt if enabled */
89 set_fiq_status(status); 89 restore_fiq(status);
90} 90}
91 91
92void pcm_play_dma_init(void) 92void pcm_play_dma_init(void)
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/timer-meg-fx.c b/firmware/target/arm/s3c2440/gigabeat-fx/timer-meg-fx.c
index 7df20f7149..b59e95806d 100644
--- a/firmware/target/arm/s3c2440/gigabeat-fx/timer-meg-fx.c
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/timer-meg-fx.c
@@ -66,7 +66,7 @@ bool __timer_set(long cycles, bool start)
66 pfn_unregister = NULL; 66 pfn_unregister = NULL;
67 } 67 }
68 68
69 oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); 69 oldlevel = disable_irq_save();
70 70
71 TCMPB0 = 0; 71 TCMPB0 = 0;
72 TCNTB0 = (unsigned int)cycles / prescaler; 72 TCNTB0 = (unsigned int)cycles / prescaler;
@@ -77,7 +77,7 @@ bool __timer_set(long cycles, bool start)
77 TCFG0 = (TCFG0 & ~0xff) | (prescaler - 1); 77 TCFG0 = (TCFG0 & ~0xff) | (prescaler - 1);
78 TCFG1 = (TCFG1 & ~0xf) | divider; 78 TCFG1 = (TCFG1 & ~0xf) | divider;
79 79
80 set_irq_level(oldlevel); 80 restore_irq(oldlevel);
81 81
82 retval = true; 82 retval = true;
83 } 83 }
diff --git a/firmware/target/arm/system-arm.h b/firmware/target/arm/system-arm.h
index 774cdbcff4..3f1dfb16c8 100644
--- a/firmware/target/arm/system-arm.h
+++ b/firmware/target/arm/system-arm.h
@@ -74,27 +74,7 @@ static inline uint32_t swap_odd_even32(uint32_t value)
74 return value; 74 return value;
75} 75}
76 76
77static inline void enable_fiq(void) 77/* Core-level interrupt masking */
78{
79 /* Clear FIQ disable bit */
80 asm volatile (
81 "mrs r0, cpsr \n"\
82 "bic r0, r0, #0x40 \n"\
83 "msr cpsr_c, r0 "
84 : : : "r0"
85 );
86}
87
88static inline void disable_fiq(void)
89{
90 /* Set FIQ disable bit */
91 asm volatile (
92 "mrs r0, cpsr \n"\
93 "orr r0, r0, #0x40 \n"\
94 "msr cpsr_c, r0 "
95 : : : "r0"
96 );
97}
98 78
99/* This one returns the old status */ 79/* This one returns the old status */
100#define IRQ_ENABLED 0x00 80#define IRQ_ENABLED 0x00
@@ -108,8 +88,10 @@ static inline void disable_fiq(void)
108#define IRQ_FIQ_STATUS 0xc0 88#define IRQ_FIQ_STATUS 0xc0
109#define HIGHEST_IRQ_LEVEL IRQ_DISABLED 89#define HIGHEST_IRQ_LEVEL IRQ_DISABLED
110 90
111#define set_irq_level(status) set_interrupt_status((status), IRQ_STATUS) 91#define set_irq_level(status) \
112#define set_fiq_status(status) set_interrupt_status((status), FIQ_STATUS) 92 set_interrupt_status((status), IRQ_STATUS)
93#define set_fiq_status(status) \
94 set_interrupt_status((status), FIQ_STATUS)
113 95
114static inline int set_interrupt_status(int status, int mask) 96static inline int set_interrupt_status(int status, int mask)
115{ 97{
@@ -122,10 +104,75 @@ static inline int set_interrupt_status(int status, int mask)
122 "orr %0, %0, %2 \n" 104 "orr %0, %0, %2 \n"
123 "msr cpsr_c, %0 \n" 105 "msr cpsr_c, %0 \n"
124 : "=&r,r"(cpsr), "=&r,r"(oldstatus) 106 : "=&r,r"(cpsr), "=&r,r"(oldstatus)
125 : "r,i"(status & mask), [mask]"i,i"(mask) 107 : "r,i"(status & mask), [mask]"i,i"(mask));
126 );
127 108
128 return oldstatus; 109 return oldstatus;
129} 110}
130 111
112static inline void enable_interrupt(int mask)
113{
114 /* Clear I and/or F disable bit */
115 int tmp;
116 asm volatile (
117 "mrs %0, cpsr \n"
118 "bic %0, %0, %1 \n"
119 "msr cpsr_c, %0 \n"
120 : "=&r"(tmp) : "i"(mask));
121}
122
123static inline void disable_interrupt(int mask)
124{
125 /* Set I and/or F disable bit */
126 int tmp;
127 asm volatile (
128 "mrs %0, cpsr \n"
129 "orr %0, %0, %1 \n"
130 "msr cpsr_c, %0 \n"
131 : "=&r"(tmp) : "i"(mask));
132}
133
134#define disable_irq(void) \
135 disable_interrupt(IRQ_STATUS)
136
137#define enable_irq(void) \
138 enable_interrupt(IRQ_STATUS)
139
140#define disable_fiq(void) \
141 disable_interrupt(FIQ_STATUS)
142
143#define enable_fiq(void) \
144 enable_interrupt(FIQ_STATUS)
145
146static inline int disable_interrupt_save(int mask)
147{
148 /* Set I and/or F disable bit and return old cpsr value */
149 int cpsr, tmp;
150 asm volatile (
151 "mrs %1, cpsr \n"
152 "orr %0, %1, %2 \n"
153 "msr cpsr_c, %0 \n"
154 : "=&r"(tmp), "=&r"(cpsr)
155 : "i"(mask));
156 return cpsr;
157}
158
159#define disable_irq_save() \
160 disable_interrupt_save(IRQ_STATUS)
161
162#define disable_fiq_save() \
163 disable_interrupt_save(FIQ_STATUS)
164
165static inline void restore_interrupt(int cpsr)
166{
167 /* Set cpsr_c from value returned by disable_interrupt_save
168 * or set_interrupt_status */
169 asm volatile ("msr cpsr_c, %0" : : "r"(cpsr));
170}
171
172#define restore_irq(cpsr) \
173 restore_interrupt(cpsr)
174
175#define restore_fiq(cpsr) \
176 restore_interrupt(cpsr)
177
131#endif /* SYSTEM_ARM_H */ 178#endif /* SYSTEM_ARM_H */
diff --git a/firmware/target/arm/tatung/tpj1022/backlight-tpj1022.c b/firmware/target/arm/tatung/tpj1022/backlight-tpj1022.c
index 933ad5e930..a466cd93dd 100644
--- a/firmware/target/arm/tatung/tpj1022/backlight-tpj1022.c
+++ b/firmware/target/arm/tatung/tpj1022/backlight-tpj1022.c
@@ -28,17 +28,17 @@
28void _backlight_on(void) 28void _backlight_on(void)
29{ 29{
30#if 0 30#if 0
31 int level = set_irq_level(HIGHEST_IRQ_LEVEL); 31 int level = disable_irq_save();
32 pcf50606_write(0x38, 0xb0); /* Backlight ON, GPO1INV=1, GPO1ACT=011 */ 32 pcf50606_write(0x38, 0xb0); /* Backlight ON, GPO1INV=1, GPO1ACT=011 */
33 set_irq_level(level); 33 restore_irq(level);
34#endif 34#endif
35} 35}
36 36
37void _backlight_off(void) 37void _backlight_off(void)
38{ 38{
39#if 0 39#if 0
40 int level = set_irq_level(HIGHEST_IRQ_LEVEL); 40 int level = disable_irq_save();
41 pcf50606_write(0x38, 0x80); /* Backlight OFF, GPO1INV=1, GPO1ACT=000 */ 41 pcf50606_write(0x38, 0x80); /* Backlight OFF, GPO1INV=1, GPO1ACT=000 */
42 set_irq_level(level); 42 restore_irq(level);
43#endif 43#endif
44} 44}
diff --git a/firmware/target/arm/tms320dm320/dsp-dm320.c b/firmware/target/arm/tms320dm320/dsp-dm320.c
index f2ca954b24..e082cf7e4d 100644
--- a/firmware/target/arm/tms320dm320/dsp-dm320.c
+++ b/firmware/target/arm/tms320dm320/dsp-dm320.c
@@ -85,7 +85,7 @@ void dsp_wake(void)
85{ 85{
86 /* If this is called concurrently, we may overlap setting and resetting the 86 /* If this is called concurrently, we may overlap setting and resetting the
87 bit, which causes lost interrupts to the DSP. */ 87 bit, which causes lost interrupts to the DSP. */
88 int old_level = set_irq_level(IRQ_DISABLED); 88 int old_level = disable_irq_save();
89 89
90 /* The first time you INT0 the DSP, the ROM loader will branch to your RST 90 /* The first time you INT0 the DSP, the ROM loader will branch to your RST
91 handler. Subsequent times, your INT0 handler will get executed. */ 91 handler. Subsequent times, your INT0 handler will get executed. */
@@ -93,7 +93,7 @@ void dsp_wake(void)
93 nop; nop; 93 nop; nop;
94 IO_DSPC_HPIB_CONTROL |= 1 << 7; 94 IO_DSPC_HPIB_CONTROL |= 1 << 7;
95 95
96 set_irq_level(old_level); 96 restore_irq(old_level);
97} 97}
98 98
99static void dsp_load(const struct dsp_section *im) 99static void dsp_load(const struct dsp_section *im)
diff --git a/firmware/target/arm/tms320dm320/timer-dm320.c b/firmware/target/arm/tms320dm320/timer-dm320.c
index 482fef9f12..e1e051d3a5 100644
--- a/firmware/target/arm/tms320dm320/timer-dm320.c
+++ b/firmware/target/arm/tms320dm320/timer-dm320.c
@@ -48,7 +48,7 @@ bool __timer_set(long cycles, bool start)
48 pfn_unregister = NULL; 48 pfn_unregister = NULL;
49 } 49 }
50 50
51 oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); 51 oldlevel = disable_irq_save();
52 52
53 /* Increase prescale values starting from 0 to make the cycle count fit */ 53 /* Increase prescale values starting from 0 to make the cycle count fit */
54 while(divider>65535 && prescaler<1024) 54 while(divider>65535 && prescaler<1024)
@@ -60,7 +60,7 @@ bool __timer_set(long cycles, bool start)
60 IO_TIMER0_TMPRSCL = prescaler; 60 IO_TIMER0_TMPRSCL = prescaler;
61 IO_TIMER0_TMDIV = divider; 61 IO_TIMER0_TMDIV = divider;
62 62
63 set_irq_level(oldlevel); 63 restore_irq(oldlevel);
64 64
65 return true; 65 return true;
66} 66}
diff --git a/firmware/target/coldfire/iaudio/adc-iaudio.c b/firmware/target/coldfire/iaudio/adc-iaudio.c
index 1895cacfe9..5a2de24692 100644
--- a/firmware/target/coldfire/iaudio/adc-iaudio.c
+++ b/firmware/target/coldfire/iaudio/adc-iaudio.c
@@ -44,7 +44,7 @@ unsigned short adc_scan(int channel)
44 int level; 44 int level;
45 int data; 45 int data;
46 46
47 level = set_irq_level(HIGHEST_IRQ_LEVEL); 47 level = disable_irq_save();
48 48
49 pcf50606_write(0x2f, adcc2_parms[channel]); 49 pcf50606_write(0x2f, adcc2_parms[channel]);
50 data = pcf50606_read(0x30); 50 data = pcf50606_read(0x30);
@@ -52,7 +52,7 @@ unsigned short adc_scan(int channel)
52 if (channel == ADC_BATTERY) 52 if (channel == ADC_BATTERY)
53 data = get_10bit_voltage(data); 53 data = get_10bit_voltage(data);
54 54
55 set_irq_level(level); 55 restore_irq(level);
56 56
57 return (unsigned short)data; 57 return (unsigned short)data;
58} 58}
diff --git a/firmware/target/coldfire/iaudio/m3/audio-m3.c b/firmware/target/coldfire/iaudio/m3/audio-m3.c
index 4edae48744..da8c43c405 100644
--- a/firmware/target/coldfire/iaudio/m3/audio-m3.c
+++ b/firmware/target/coldfire/iaudio/m3/audio-m3.c
@@ -33,7 +33,7 @@ void audio_set_output_source(int source)
33 txsrc = (4 << 8); /* recording, iis1RcvData */ 33 txsrc = (4 << 8); /* recording, iis1RcvData */
34 34
35 IIS1CONFIG = (IIS1CONFIG & ~(7 << 8)) | txsrc; 35 IIS1CONFIG = (IIS1CONFIG & ~(7 << 8)) | txsrc;
36 set_irq_level(level); 36 restore_irq(level);
37} /* audio_set_output_source */ 37} /* audio_set_output_source */
38 38
39void audio_input_mux(int source, unsigned flags) 39void audio_input_mux(int source, unsigned flags)
diff --git a/firmware/target/coldfire/iaudio/m5/audio-m5.c b/firmware/target/coldfire/iaudio/m5/audio-m5.c
index 87a7c35574..024621be64 100644
--- a/firmware/target/coldfire/iaudio/m5/audio-m5.c
+++ b/firmware/target/coldfire/iaudio/m5/audio-m5.c
@@ -32,7 +32,7 @@ void audio_set_output_source(int source)
32 txsrc = (4 << 8); /* recording, iis1RcvData */ 32 txsrc = (4 << 8); /* recording, iis1RcvData */
33 33
34 IIS1CONFIG = (IIS1CONFIG & ~(7 << 8)) | txsrc; 34 IIS1CONFIG = (IIS1CONFIG & ~(7 << 8)) | txsrc;
35 set_irq_level(level); 35 restore_irq(level);
36} /* audio_set_output_source */ 36} /* audio_set_output_source */
37 37
38void audio_input_mux(int source, unsigned flags) 38void audio_input_mux(int source, unsigned flags)
diff --git a/firmware/target/coldfire/iaudio/m5/backlight-m5.c b/firmware/target/coldfire/iaudio/m5/backlight-m5.c
index 19bc5bfcae..3461a330ec 100644
--- a/firmware/target/coldfire/iaudio/m5/backlight-m5.c
+++ b/firmware/target/coldfire/iaudio/m5/backlight-m5.c
@@ -33,18 +33,18 @@ bool _backlight_init(void)
33 33
34void _backlight_on(void) 34void _backlight_on(void)
35{ 35{
36 int level = set_irq_level(HIGHEST_IRQ_LEVEL); 36 int level = disable_irq_save();
37 37
38 pcf50606_write(0x39, 0x07); 38 pcf50606_write(0x39, 0x07);
39 set_irq_level(level); 39 restore_irq(level);
40} 40}
41 41
42void _backlight_off(void) 42void _backlight_off(void)
43{ 43{
44 int level = set_irq_level(HIGHEST_IRQ_LEVEL); 44 int level = disable_irq_save();
45 45
46 pcf50606_write(0x39, 0x00); 46 pcf50606_write(0x39, 0x00);
47 set_irq_level(level); 47 restore_irq(level);
48} 48}
49 49
50void _remote_backlight_on(void) 50void _remote_backlight_on(void)
diff --git a/firmware/target/coldfire/iaudio/m5/power-m5.c b/firmware/target/coldfire/iaudio/m5/power-m5.c
index 939cae02f2..18401af49f 100644
--- a/firmware/target/coldfire/iaudio/m5/power-m5.c
+++ b/firmware/target/coldfire/iaudio/m5/power-m5.c
@@ -44,16 +44,16 @@ bool charger_inserted(void)
44void ide_power_enable(bool on) 44void ide_power_enable(bool on)
45{ 45{
46 /* GPOOD3 */ 46 /* GPOOD3 */
47 int level = set_irq_level(HIGHEST_IRQ_LEVEL); 47 int level = disable_irq_save();
48 pcf50606_write(0x3c, on ? 0x07 : 0x00); 48 pcf50606_write(0x3c, on ? 0x07 : 0x00);
49 set_irq_level(level); 49 restore_irq(level);
50} 50}
51 51
52bool ide_powered(void) 52bool ide_powered(void)
53{ 53{
54 int level = set_irq_level(HIGHEST_IRQ_LEVEL); 54 int level = disable_irq_save();
55 int value = pcf50606_read(0x3c); 55 int value = pcf50606_read(0x3c);
56 set_irq_level(level); 56 restore_irq(level);
57 return (value & 0x07) != 0; 57 return (value & 0x07) != 0;
58} 58}
59 59
diff --git a/firmware/target/coldfire/iaudio/pcf50606-iaudio.c b/firmware/target/coldfire/iaudio/pcf50606-iaudio.c
index 0614355b5d..14b45e78b5 100644
--- a/firmware/target/coldfire/iaudio/pcf50606-iaudio.c
+++ b/firmware/target/coldfire/iaudio/pcf50606-iaudio.c
@@ -94,9 +94,9 @@ void pcf50606_init(void)
94 94
95void pcf50606_reset_timeout(void) 95void pcf50606_reset_timeout(void)
96{ 96{
97 int level = set_irq_level(HIGHEST_IRQ_LEVEL); 97 int level = disable_irq_save();
98 pcf50606_write(0x08, pcf50606_read(0x08) | 0x02); /* OOCC1 - TOTRST=1 */ 98 pcf50606_write(0x08, pcf50606_read(0x08) | 0x02); /* OOCC1 - TOTRST=1 */
99 set_irq_level(level); 99 restore_irq(level);
100} 100}
101 101
102/* Handles interrupts generated by the pcf50606 */ 102/* Handles interrupts generated by the pcf50606 */
diff --git a/firmware/target/coldfire/iaudio/x5/audio-x5.c b/firmware/target/coldfire/iaudio/x5/audio-x5.c
index 594ff3b574..0ae5f6023a 100644
--- a/firmware/target/coldfire/iaudio/x5/audio-x5.c
+++ b/firmware/target/coldfire/iaudio/x5/audio-x5.c
@@ -32,7 +32,7 @@ void audio_set_output_source(int source)
32 txsrc = (4 << 8); /* recording, iis1RcvData */ 32 txsrc = (4 << 8); /* recording, iis1RcvData */
33 33
34 IIS1CONFIG = (IIS1CONFIG & ~(7 << 8)) | txsrc; 34 IIS1CONFIG = (IIS1CONFIG & ~(7 << 8)) | txsrc;
35 set_irq_level(level); 35 restore_irq(level);
36} /* audio_set_output_source */ 36} /* audio_set_output_source */
37 37
38void audio_input_mux(int source, unsigned flags) 38void audio_input_mux(int source, unsigned flags)
diff --git a/firmware/target/coldfire/iaudio/x5/backlight-x5.c b/firmware/target/coldfire/iaudio/x5/backlight-x5.c
index ebb28fbf2b..13ccad5adf 100644
--- a/firmware/target/coldfire/iaudio/x5/backlight-x5.c
+++ b/firmware/target/coldfire/iaudio/x5/backlight-x5.c
@@ -39,16 +39,16 @@ void _backlight_on(void)
39#ifndef BOOTLOADER 39#ifndef BOOTLOADER
40 _lcd_sleep_timer = 0; /* LCD should be awake already */ 40 _lcd_sleep_timer = 0; /* LCD should be awake already */
41#endif 41#endif
42 level = set_irq_level(HIGHEST_IRQ_LEVEL); 42 level = disable_irq_save();
43 pcf50606_write(0x38, 0xb0); /* Backlight ON, GPO1INV=1, GPO1ACT=011 */ 43 pcf50606_write(0x38, 0xb0); /* Backlight ON, GPO1INV=1, GPO1ACT=011 */
44 set_irq_level(level); 44 restore_irq(level);
45} 45}
46 46
47void _backlight_off(void) 47void _backlight_off(void)
48{ 48{
49 int level = set_irq_level(HIGHEST_IRQ_LEVEL); 49 int level = disable_irq_save();
50 pcf50606_write(0x38, 0x80); /* Backlight OFF, GPO1INV=1, GPO1ACT=000 */ 50 pcf50606_write(0x38, 0x80); /* Backlight OFF, GPO1INV=1, GPO1ACT=000 */
51 set_irq_level(level); 51 restore_irq(level);
52 lcd_enable(false); 52 lcd_enable(false);
53#ifndef BOOTLOADER 53#ifndef BOOTLOADER
54 /* Start LCD sleep countdown */ 54 /* Start LCD sleep countdown */
@@ -66,10 +66,10 @@ void _backlight_off(void)
66void _backlight_set_brightness(int val) 66void _backlight_set_brightness(int val)
67{ 67{
68 /* disable IRQs while bitbanging */ 68 /* disable IRQs while bitbanging */
69 int old_irq_level = set_irq_level(HIGHEST_IRQ_LEVEL); 69 int old_irq_level = disable_irq_save();
70 pcf50606_write(0x35, (val << 1) | 0x01); /* 512Hz, Enable PWM */ 70 pcf50606_write(0x35, (val << 1) | 0x01); /* 512Hz, Enable PWM */
71 /* enable IRQs again */ 71 /* enable IRQs again */
72 set_irq_level(old_irq_level); 72 restore_irq(old_irq_level);
73} 73}
74 74
75void _remote_backlight_on(void) 75void _remote_backlight_on(void)
diff --git a/firmware/target/coldfire/iaudio/x5/ds2411-x5.c b/firmware/target/coldfire/iaudio/x5/ds2411-x5.c
index dc5a188ae1..a9bf20f727 100644
--- a/firmware/target/coldfire/iaudio/x5/ds2411-x5.c
+++ b/firmware/target/coldfire/iaudio/x5/ds2411-x5.c
@@ -134,7 +134,7 @@ static unsigned char ds2411_read_byte(void)
134 */ 134 */
135int ds2411_read_id(struct ds2411_id *id) 135int ds2411_read_id(struct ds2411_id *id)
136{ 136{
137 int level = set_irq_level(DISABLE_INTERRUPTS); /* Timing sensitive */ 137 int level = disable_irq_save(); /* Timing sensitive */
138 int i; 138 int i;
139 unsigned char crc; 139 unsigned char crc;
140 140
@@ -208,7 +208,7 @@ int ds2411_read_id(struct ds2411_id *id)
208 i = DS2411_NO_PRESENCE; 208 i = DS2411_NO_PRESENCE;
209 } 209 }
210 210
211 set_irq_level(level); 211 restore_irq(level);
212 212
213 return i; 213 return i;
214} /* ds2411_read_id */ 214} /* ds2411_read_id */
diff --git a/firmware/target/coldfire/iaudio/x5/power-x5.c b/firmware/target/coldfire/iaudio/x5/power-x5.c
index 068b25f577..f5193aa559 100644
--- a/firmware/target/coldfire/iaudio/x5/power-x5.c
+++ b/firmware/target/coldfire/iaudio/x5/power-x5.c
@@ -44,16 +44,16 @@ bool charger_inserted(void)
44void ide_power_enable(bool on) 44void ide_power_enable(bool on)
45{ 45{
46 /* GPOOD3 */ 46 /* GPOOD3 */
47 int level = set_irq_level(HIGHEST_IRQ_LEVEL); 47 int level = disable_irq_save();
48 pcf50606_write(0x3c, on ? 0x07 : 0x00); 48 pcf50606_write(0x3c, on ? 0x07 : 0x00);
49 set_irq_level(level); 49 restore_irq(level);
50} 50}
51 51
52bool ide_powered(void) 52bool ide_powered(void)
53{ 53{
54 int level = set_irq_level(HIGHEST_IRQ_LEVEL); 54 int level = disable_irq_save();
55 int value = pcf50606_read(0x3c); 55 int value = pcf50606_read(0x3c);
56 set_irq_level(level); 56 restore_irq(level);
57 return (value & 0x07) != 0; 57 return (value & 0x07) != 0;
58} 58}
59 59
diff --git a/firmware/target/coldfire/iriver/audio-iriver.c b/firmware/target/coldfire/iriver/audio-iriver.c
index 4d22e7c987..51917b1338 100644
--- a/firmware/target/coldfire/iriver/audio-iriver.c
+++ b/firmware/target/coldfire/iriver/audio-iriver.c
@@ -41,7 +41,7 @@ void audio_set_output_source(int source)
41 41
42 IIS2CONFIG = (IIS2CONFIG & ~(7 << 8)) | (txsrc_select[source+1] << 8); 42 IIS2CONFIG = (IIS2CONFIG & ~(7 << 8)) | (txsrc_select[source+1] << 8);
43 43
44 set_irq_level(level); 44 restore_irq(level);
45} /* audio_set_output_source */ 45} /* audio_set_output_source */
46 46
47void audio_input_mux(int source, unsigned flags) 47void audio_input_mux(int source, unsigned flags)
diff --git a/firmware/target/coldfire/iriver/h100/adc-h100.c b/firmware/target/coldfire/iriver/h100/adc-h100.c
index 40fcc8925d..7ea7618b09 100644
--- a/firmware/target/coldfire/iriver/h100/adc-h100.c
+++ b/firmware/target/coldfire/iriver/h100/adc-h100.c
@@ -47,7 +47,7 @@
47 47
48unsigned short adc_scan(int channel) 48unsigned short adc_scan(int channel)
49{ 49{
50 int level = set_irq_level(HIGHEST_IRQ_LEVEL); 50 int level = disable_irq_save();
51 unsigned char data = 0; 51 unsigned char data = 0;
52 int i; 52 int i;
53 53
@@ -97,7 +97,7 @@ unsigned short adc_scan(int channel)
97 97
98 CS_HI; 98 CS_HI;
99 99
100 set_irq_level(level); 100 restore_irq(level);
101 return data; 101 return data;
102} 102}
103 103
diff --git a/firmware/target/coldfire/iriver/h100/power-h100.c b/firmware/target/coldfire/iriver/h100/power-h100.c
index 5dc8618cc6..7ecf961842 100644
--- a/firmware/target/coldfire/iriver/h100/power-h100.c
+++ b/firmware/target/coldfire/iriver/h100/power-h100.c
@@ -115,8 +115,7 @@ void power_off(void)
115 set_irq_level(DISABLE_INTERRUPTS); 115 set_irq_level(DISABLE_INTERRUPTS);
116 and_l(~0x00080000, &GPIO1_OUT); 116 and_l(~0x00080000, &GPIO1_OUT);
117 asm("halt"); 117 asm("halt");
118 while(1) 118 while(1);
119 yield();
120} 119}
121 120
122#endif /* SIMULATOR */ 121#endif /* SIMULATOR */
diff --git a/firmware/target/coldfire/iriver/h100/spdif-h100.c b/firmware/target/coldfire/iriver/h100/spdif-h100.c
index beede3fdce..380622422c 100644
--- a/firmware/target/coldfire/iriver/h100/spdif-h100.c
+++ b/firmware/target/coldfire/iriver/h100/spdif-h100.c
@@ -99,7 +99,7 @@ void spdif_set_output_source(int source, bool src_on)
99 PDOR3 = 0; /* A write to the FIFO kick-starts playback */ 99 PDOR3 = 0; /* A write to the FIFO kick-starts playback */
100 } 100 }
101 101
102 set_irq_level(level); 102 restore_irq(level);
103} /* spdif_set_output_source */ 103} /* spdif_set_output_source */
104 104
105/* Return the last set S/PDIF audio source */ 105/* Return the last set S/PDIF audio source */
diff --git a/firmware/target/coldfire/iriver/h300/adc-h300.c b/firmware/target/coldfire/iriver/h300/adc-h300.c
index b13d0c73cc..efe5a9d746 100644
--- a/firmware/target/coldfire/iriver/h300/adc-h300.c
+++ b/firmware/target/coldfire/iriver/h300/adc-h300.c
@@ -34,7 +34,7 @@ static int adcc2_parms[] =
34 34
35unsigned short adc_scan(int channel) 35unsigned short adc_scan(int channel)
36{ 36{
37 int level = set_irq_level(HIGHEST_IRQ_LEVEL); 37 int level = disable_irq_save();
38 unsigned data; 38 unsigned data;
39 39
40 pcf50606_write(0x2f, adcc2_parms[channel]); 40 pcf50606_write(0x2f, adcc2_parms[channel]);
@@ -43,6 +43,6 @@ unsigned short adc_scan(int channel)
43 if (channel == ADC_BATTERY) 43 if (channel == ADC_BATTERY)
44 data = (data << 2) | (pcf50606_read(0x31) & 0x03); 44 data = (data << 2) | (pcf50606_read(0x31) & 0x03);
45 45
46 set_irq_level(level); 46 restore_irq(level);
47 return data; 47 return data;
48} 48}
diff --git a/firmware/target/coldfire/iriver/h300/backlight-h300.c b/firmware/target/coldfire/iriver/h300/backlight-h300.c
index c0d441ad3f..f042ee5524 100644
--- a/firmware/target/coldfire/iriver/h300/backlight-h300.c
+++ b/firmware/target/coldfire/iriver/h300/backlight-h300.c
@@ -51,10 +51,10 @@ void _backlight_off(void)
51void _backlight_set_brightness(int val) 51void _backlight_set_brightness(int val)
52{ 52{
53 /* disable IRQs while bitbanging */ 53 /* disable IRQs while bitbanging */
54 int old_irq_level = set_irq_level(HIGHEST_IRQ_LEVEL); 54 int old_irq_level = disable_irq_save();
55 pcf50606_write(0x35, (val << 1) | 0x01); /* 512Hz, Enable PWM */ 55 pcf50606_write(0x35, (val << 1) | 0x01); /* 512Hz, Enable PWM */
56 /* enable IRQs again */ 56 /* enable IRQs again */
57 set_irq_level(old_irq_level); 57 restore_irq(old_irq_level);
58} 58}
59 59
60void _remote_backlight_on(void) 60void _remote_backlight_on(void)
diff --git a/firmware/target/coldfire/iriver/h300/power-h300.c b/firmware/target/coldfire/iriver/h300/power-h300.c
index 21c723da8e..a06763e555 100644
--- a/firmware/target/coldfire/iriver/h300/power-h300.c
+++ b/firmware/target/coldfire/iriver/h300/power-h300.c
@@ -86,8 +86,7 @@ void power_off(void)
86 set_irq_level(DISABLE_INTERRUPTS); 86 set_irq_level(DISABLE_INTERRUPTS);
87 and_l(~0x00080000, &GPIO1_OUT); 87 and_l(~0x00080000, &GPIO1_OUT);
88 asm("halt"); 88 asm("halt");
89 while(1) 89 while(1);
90 yield();
91} 90}
92 91
93#endif /* SIMULATOR */ 92#endif /* SIMULATOR */
diff --git a/firmware/target/coldfire/iriver/lcd-remote-iriver.c b/firmware/target/coldfire/iriver/lcd-remote-iriver.c
index cab7cc4104..2fe5d6c3c1 100644
--- a/firmware/target/coldfire/iriver/lcd-remote-iriver.c
+++ b/firmware/target/coldfire/iriver/lcd-remote-iriver.c
@@ -478,9 +478,9 @@ static void remote_tick(void)
478 if (!(countdown % 8)) 478 if (!(countdown % 8))
479 { 479 {
480 /* Determine which type of remote it is */ 480 /* Determine which type of remote it is */
481 level = set_irq_level(HIGHEST_IRQ_LEVEL); 481 level = disable_irq_save();
482 val = adc_scan(ADC_REMOTEDETECT); 482 val = adc_scan(ADC_REMOTEDETECT);
483 set_irq_level(level); 483 restore_irq(level);
484 484
485 if (val < ADCVAL_H100_LCD_REMOTE_HOLD) 485 if (val < ADCVAL_H100_LCD_REMOTE_HOLD)
486 { 486 {
diff --git a/firmware/target/coldfire/pcm-coldfire.c b/firmware/target/coldfire/pcm-coldfire.c
index 105ad51de6..2614946543 100644
--- a/firmware/target/coldfire/pcm-coldfire.c
+++ b/firmware/target/coldfire/pcm-coldfire.c
@@ -158,7 +158,7 @@ void _pcm_apply_settings_irq_lock(bool clear_reset)
158{ 158{
159 int level = set_irq_level(DMA_IRQ_LEVEL); 159 int level = set_irq_level(DMA_IRQ_LEVEL);
160 _pcm_apply_settings(clear_reset); 160 _pcm_apply_settings(clear_reset);
161 set_irq_level(level); 161 restore_irq(level);
162} 162}
163 163
164/* This clears the reset bit to enable monitoring immediately if monitoring 164/* This clears the reset bit to enable monitoring immediately if monitoring
@@ -175,7 +175,7 @@ void pcm_apply_settings(void)
175 if (_pcm_apply_settings(!pbm || kick) && kick) 175 if (_pcm_apply_settings(!pbm || kick) && kick)
176 PDOR3 = 0; /* Kick FIFO out of reset by writing to it */ 176 PDOR3 = 0; /* Kick FIFO out of reset by writing to it */
177 177
178 set_irq_level(level); 178 restore_irq(level);
179} /* pcm_apply_settings */ 179} /* pcm_apply_settings */
180 180
181void pcm_play_dma_init(void) 181void pcm_play_dma_init(void)
diff --git a/firmware/target/coldfire/system-coldfire.c b/firmware/target/coldfire/system-coldfire.c
index 60f7ab12ad..67c684f95a 100644
--- a/firmware/target/coldfire/system-coldfire.c
+++ b/firmware/target/coldfire/system-coldfire.c
@@ -351,5 +351,5 @@ void coldfire_set_dataincontrol(unsigned long value)
351 /* Have to be atomic against recording stop initiated by DMA1 */ 351 /* Have to be atomic against recording stop initiated by DMA1 */
352 int level = set_irq_level(DMA_IRQ_LEVEL); 352 int level = set_irq_level(DMA_IRQ_LEVEL);
353 DATAINCONTROL = (DATAINCONTROL & (1 << 9)) | value; 353 DATAINCONTROL = (DATAINCONTROL & (1 << 9)) | value;
354 set_irq_level(level); 354 restore_irq(level);
355} 355}
diff --git a/firmware/target/coldfire/system-target.h b/firmware/target/coldfire/system-target.h
index 8e3a2a3d5a..14b3207c0c 100644
--- a/firmware/target/coldfire/system-target.h
+++ b/firmware/target/coldfire/system-target.h
@@ -81,13 +81,54 @@ static inline int set_irq_level(int level)
81{ 81{
82 int oldlevel; 82 int oldlevel;
83 /* Read the old level and set the new one */ 83 /* Read the old level and set the new one */
84 asm volatile ("move.w %%sr, %0 \n" 84
85 "bset.l #13, %1 \n" /* Keep supervisor state set */ 85 /* Not volatile - can be removed if oldlevel isn't used */
86 "move.w %1, %%sr \n" 86 asm ("move.w %%sr, %0" : "=d"(oldlevel));
87 : "=d"(oldlevel), "+d"(level)); 87 /* Keep supervisor state set */
88 asm volatile ("move.w %0, %%sr \n" : : "d"(level | 0x2000));
89 return oldlevel;
90}
91
92/* Enable all interrupts */
93static inline void enable_irq(void)
94{
95 int tmp;
96 /* Using move.w over the compiler's move.l saves 2 bytes per instance */
97 asm volatile ("move.w %1, %0 \n"
98 "move.w %0, %%sr \n"
99 : "=&d"(tmp) : "i"(0x2000));
100}
101
102/* Disable interrupts up to HIGHEST_IRQ_LEVEL */
103static inline void disable_irq(void)
104{
105 int tmp;
106 /* Using move.w over the compiler's move.l saves 2 bytes per instance */
107 asm volatile ("move.w %1, %0 \n"
108 "move.w %0, %%sr \n"
109 : "=&d"(tmp)
110 : "i"(0x2000 | HIGHEST_IRQ_LEVEL));
111}
112
113static inline int disable_irq_save(void)
114{
115 int oldlevel, tmp;
116 /* Using move.w over the compiler's move.l saves 2 bytes per instance */
117 asm volatile ("move.w %%sr, %1 \n"
118 "move.w %2, %0 \n"
119 "move.w %0, %%sr \n"
120 : "=&d"(tmp), "=d"(oldlevel)
121 : "i"(0x2000 | HIGHEST_IRQ_LEVEL));
88 return oldlevel; 122 return oldlevel;
89} 123}
90 124
125static inline void restore_irq(int oldlevel)
126{
127 /* Restore the sr value returned by disable_irq_save or
128 * set_irq_level */
129 asm volatile ("move.w %0, %%sr" : : "d"(oldlevel));
130}
131
91static inline uint16_t swap16(uint16_t value) 132static inline uint16_t swap16(uint16_t value)
92 /* 133 /*
93 result[15..8] = value[ 7..0]; 134 result[15..8] = value[ 7..0];
diff --git a/firmware/target/sh/archos/fm_v2/power-fm_v2.c b/firmware/target/sh/archos/fm_v2/power-fm_v2.c
index 94a36339bb..ac23348d42 100644
--- a/firmware/target/sh/archos/fm_v2/power-fm_v2.c
+++ b/firmware/target/sh/archos/fm_v2/power-fm_v2.c
@@ -101,9 +101,8 @@ bool ide_powered(void)
101 101
102void power_off(void) 102void power_off(void)
103{ 103{
104 set_irq_level(HIGHEST_IRQ_LEVEL); 104 disable_irq();
105 and_b(~0x20, &PBDRL); 105 and_b(~0x20, &PBDRL);
106 or_b(0x20, &PBIORL); 106 or_b(0x20, &PBIORL);
107 while(1) 107 while(1);
108 yield();
109} 108}
diff --git a/firmware/target/sh/archos/ondio/power-ondio.c b/firmware/target/sh/archos/ondio/power-ondio.c
index 156516afeb..87f365791b 100644
--- a/firmware/target/sh/archos/ondio/power-ondio.c
+++ b/firmware/target/sh/archos/ondio/power-ondio.c
@@ -66,13 +66,12 @@ void power_init(void)
66 66
67void power_off(void) 67void power_off(void)
68{ 68{
69 set_irq_level(HIGHEST_IRQ_LEVEL); 69 disable_irq();
70#ifdef HAVE_BACKLIGHT 70#ifdef HAVE_BACKLIGHT
71 /* Switch off the light on backlight-modded Ondios */ 71 /* Switch off the light on backlight-modded Ondios */
72 _backlight_off(); 72 _backlight_off();
73#endif 73#endif
74 and_b(~0x20, &PBDRL); 74 and_b(~0x20, &PBDRL);
75 or_b(0x20, &PBIORL); 75 or_b(0x20, &PBIORL);
76 while(1) 76 while(1);
77 yield();
78} 77}
diff --git a/firmware/target/sh/archos/player/power-player.c b/firmware/target/sh/archos/player/power-player.c
index 7d9d0d7d16..b2f51b9280 100644
--- a/firmware/target/sh/archos/player/power-player.c
+++ b/firmware/target/sh/archos/player/power-player.c
@@ -79,9 +79,8 @@ bool ide_powered(void)
79 79
80void power_off(void) 80void power_off(void)
81{ 81{
82 set_irq_level(HIGHEST_IRQ_LEVEL); 82 disable_irq();
83 and_b(~0x08, &PADRH); 83 and_b(~0x08, &PADRH);
84 or_b(0x08, &PAIORH); 84 or_b(0x08, &PAIORH);
85 while(1) 85 while(1);
86 yield();
87} 86}
diff --git a/firmware/target/sh/archos/recorder/power-recorder.c b/firmware/target/sh/archos/recorder/power-recorder.c
index 2af8df1bb6..1804bcb660 100644
--- a/firmware/target/sh/archos/recorder/power-recorder.c
+++ b/firmware/target/sh/archos/recorder/power-recorder.c
@@ -95,9 +95,8 @@ bool ide_powered(void)
95 95
96void power_off(void) 96void power_off(void)
97{ 97{
98 set_irq_level(HIGHEST_IRQ_LEVEL); 98 disable_irq();
99 and_b(~0x10, &PBDRL); 99 and_b(~0x10, &PBDRL);
100 or_b(0x10, &PBIORL); 100 or_b(0x10, &PBIORL);
101 while(1) 101 while(1);
102 yield();
103} 102}
diff --git a/firmware/target/sh/system-sh.c b/firmware/target/sh/system-sh.c
index eec3ec18e4..f763e0ff53 100644
--- a/firmware/target/sh/system-sh.c
+++ b/firmware/target/sh/system-sh.c
@@ -360,7 +360,7 @@ void system_init(void)
360 360
361void system_reboot (void) 361void system_reboot (void)
362{ 362{
363 set_irq_level(HIGHEST_IRQ_LEVEL); 363 disable_irq();
364 364
365 asm volatile ("ldc\t%0,vbr" : : "r"(0)); 365 asm volatile ("ldc\t%0,vbr" : : "r"(0));
366 366
diff --git a/firmware/target/sh/system-target.h b/firmware/target/sh/system-target.h
index 7fb8fecb6b..d641076694 100644
--- a/firmware/target/sh/system-target.h
+++ b/firmware/target/sh/system-target.h
@@ -52,11 +52,29 @@ static inline int set_irq_level(int level)
52{ 52{
53 int i; 53 int i;
54 /* Read the old level and set the new one */ 54 /* Read the old level and set the new one */
55 asm volatile ("stc sr, %0" : "=r" (i)); 55
56 /* Not volatile - will be optimized away if the return value isn't used */
57 asm ("stc sr, %0" : "=r" (i));
56 asm volatile ("ldc %0, sr" : : "r" (level)); 58 asm volatile ("ldc %0, sr" : : "r" (level));
57 return i; 59 return i;
58} 60}
59 61
62static inline void enable_irq(void)
63{
64 int i;
65 asm volatile ("mov %1, %0 \n" /* Save a constant load from RAM */
66 "ldc %0, sr \n" : "=&r"(i) : "i"(0));
67}
68
69#define disable_irq() \
70 ((void)set_irq_level(HIGHEST_IRQ_LEVEL))
71
72#define disable_irq_save() \
73 set_irq_level(HIGHEST_IRQ_LEVEL)
74
75#define restore_irq(i) \
76 ((void)set_irq_level(i))
77
60static inline uint16_t swap16(uint16_t value) 78static inline uint16_t swap16(uint16_t value)
61 /* 79 /*
62 result[15..8] = value[ 7..0]; 80 result[15..8] = value[ 7..0];
diff --git a/firmware/test/i2c/main.c b/firmware/test/i2c/main.c
index 0d54da5dea..e094a0b32e 100644
--- a/firmware/test/i2c/main.c
+++ b/firmware/test/i2c/main.c
@@ -542,7 +542,7 @@ int main(void)
542 542
543 543
544 544
545 set_irq_level(0); 545 enable_irq();
546 546
547 547
548 548
diff --git a/firmware/test/kernel/main.c b/firmware/test/kernel/main.c
index 99642c867d..cc0d93a6b4 100644
--- a/firmware/test/kernel/main.c
+++ b/firmware/test/kernel/main.c
@@ -59,7 +59,7 @@ int main(void)
59 59
60 kernel_init(); 60 kernel_init();
61 61
62 set_irq_level(0); 62 enable_irq();
63 63
64 tick_add_task(testfunc); 64 tick_add_task(testfunc);
65 65
diff --git a/firmware/thread.c b/firmware/thread.c
index 259a66a652..2ac7f6efc3 100644
--- a/firmware/thread.c
+++ b/firmware/thread.c
@@ -399,7 +399,7 @@ static inline void core_sleep(void)
399{ 399{
400 PROC_CTL(CURRENT_CORE) = PROC_SLEEP; 400 PROC_CTL(CURRENT_CORE) = PROC_SLEEP;
401 nop; nop; nop; 401 nop; nop; nop;
402 set_irq_level(IRQ_ENABLED); 402 enable_irq();
403} 403}
404#else 404#else
405static inline void core_sleep(unsigned int core) 405static inline void core_sleep(unsigned int core)
@@ -421,9 +421,6 @@ static inline void core_sleep(unsigned int core)
421 "ldr r1, [%[mbx], #0] \n" 421 "ldr r1, [%[mbx], #0] \n"
422 "tst r1, r0, lsr #2 \n" 422 "tst r1, r0, lsr #2 \n"
423 "bne 1b \n" 423 "bne 1b \n"
424 "mrs r1, cpsr \n" /* Enable IRQ */
425 "bic r1, r1, #0x80 \n"
426 "msr cpsr_c, r1 \n"
427 : 424 :
428 : [ctl]"r"(&PROC_CTL(CPU)), [mbx]"r"(MBX_BASE), [c]"r"(core) 425 : [ctl]"r"(&PROC_CTL(CPU)), [mbx]"r"(MBX_BASE), [c]"r"(core)
429 : "r0", "r1"); 426 : "r0", "r1");
@@ -443,10 +440,8 @@ static inline void core_sleep(unsigned int core)
443 440
444 /* Wait for other processor to finish wake procedure */ 441 /* Wait for other processor to finish wake procedure */
445 while (MBX_MSG_STAT & (0x1 << core)); 442 while (MBX_MSG_STAT & (0x1 << core));
446
447 /* Enable IRQ */
448 set_irq_level(IRQ_ENABLED);
449#endif /* ASM/C selection */ 443#endif /* ASM/C selection */
444 enable_irq();
450} 445}
451#endif /* NUM_CORES */ 446#endif /* NUM_CORES */
452#elif CONFIG_CPU == PP5002 447#elif CONFIG_CPU == PP5002
@@ -465,13 +460,11 @@ static inline void core_sleep(void)
465 "nop \n" /* nop's needed because of pipeline */ 460 "nop \n" /* nop's needed because of pipeline */
466 "nop \n" 461 "nop \n"
467 "nop \n" 462 "nop \n"
468 "mrs r0, cpsr \n" /* Enable IRQ */
469 "bic r0, r0, #0x80 \n"
470 "msr cpsr_c, r0 \n"
471 : 463 :
472 : [ctl]"r"(&PROC_CTL(CURRENT_CORE)) 464 : [ctl]"r"(&PROC_CTL(CURRENT_CORE))
473 : "r0" 465 : "r0"
474 ); 466 );
467 enable_irq();
475} 468}
476#else 469#else
477/* PP5002 has no mailboxes - emulate using bytes */ 470/* PP5002 has no mailboxes - emulate using bytes */
@@ -503,9 +496,6 @@ static inline void core_sleep(unsigned int core)
503 "ldrb r0, [%[sem], #0] \n" 496 "ldrb r0, [%[sem], #0] \n"
504 "cmp r0, #0 \n" 497 "cmp r0, #0 \n"
505 "bne 1b \n" 498 "bne 1b \n"
506 "mrs r0, cpsr \n" /* Enable IRQ */
507 "bic r0, r0, #0x80 \n"
508 "msr cpsr_c, r0 \n"
509 : 499 :
510 : [sem]"r"(&core_semaphores[core]), [c]"r"(core), 500 : [sem]"r"(&core_semaphores[core]), [c]"r"(core),
511 [ctl]"r"(&PROC_CTL(CPU)) 501 [ctl]"r"(&PROC_CTL(CPU))
@@ -530,8 +520,8 @@ static inline void core_sleep(unsigned int core)
530 while (core_semaphores[core].intend_wake != 0); 520 while (core_semaphores[core].intend_wake != 0);
531 521
532 /* Enable IRQ */ 522 /* Enable IRQ */
533 set_irq_level(IRQ_ENABLED);
534#endif /* ASM/C selection */ 523#endif /* ASM/C selection */
524 enable_irq();
535} 525}
536#endif /* NUM_CORES */ 526#endif /* NUM_CORES */
537#endif /* PP CPU type */ 527#endif /* PP CPU type */
@@ -578,7 +568,7 @@ void core_wake(unsigned int othercore)
578 : "r1", "r2", "r3"); 568 : "r1", "r2", "r3");
579#else /* C version for reference */ 569#else /* C version for reference */
580 /* Disable interrupts - avoid reentrancy from the tick */ 570 /* Disable interrupts - avoid reentrancy from the tick */
581 int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); 571 int oldlevel = disable_irq_save();
582 572
583 /* Signal intent to wake other processor - set stay awake */ 573 /* Signal intent to wake other processor - set stay awake */
584 MBX_MSG_SET = 0x11 << othercore; 574 MBX_MSG_SET = 0x11 << othercore;
@@ -593,7 +583,7 @@ void core_wake(unsigned int othercore)
593 583
594 /* Done with wake procedure */ 584 /* Done with wake procedure */
595 MBX_MSG_CLR = 0x1 << othercore; 585 MBX_MSG_CLR = 0x1 << othercore;
596 set_irq_level(oldlevel); 586 restore_irq(oldlevel);
597#endif /* ASM/C selection */ 587#endif /* ASM/C selection */
598} 588}
599#elif CONFIG_CPU == PP5002 589#elif CONFIG_CPU == PP5002
@@ -631,7 +621,7 @@ void core_wake(unsigned int othercore)
631 ); 621 );
632#else /* C version for reference */ 622#else /* C version for reference */
633 /* Disable interrupts - avoid reentrancy from the tick */ 623 /* Disable interrupts - avoid reentrancy from the tick */
634 int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); 624 int oldlevel = disable_irq_save();
635 625
636 /* Signal intent to wake other processor - set stay awake */ 626 /* Signal intent to wake other processor - set stay awake */
637 core_semaphores[othercore].intend_wake = 1; 627 core_semaphores[othercore].intend_wake = 1;
@@ -647,7 +637,7 @@ void core_wake(unsigned int othercore)
647 637
648 /* Done with wake procedure */ 638 /* Done with wake procedure */
649 core_semaphores[othercore].intend_wake = 0; 639 core_semaphores[othercore].intend_wake = 0;
650 set_irq_level(oldlevel); 640 restore_irq(oldlevel);
651#endif /* ASM/C selection */ 641#endif /* ASM/C selection */
652} 642}
653#endif /* CPU type */ 643#endif /* CPU type */
@@ -775,7 +765,7 @@ static inline void core_sleep(void)
775static inline void core_sleep(void) 765static inline void core_sleep(void)
776{ 766{
777 #warning TODO: Implement core_sleep 767 #warning TODO: Implement core_sleep
778 set_irq_level(IRQ_ENABLED); 768 enable_irq();
779} 769}
780#elif defined(CPU_TCC780X) 770#elif defined(CPU_TCC780X)
781static inline void core_sleep(void) 771static inline void core_sleep(void)
@@ -784,11 +774,9 @@ static inline void core_sleep(void)
784 asm volatile ( 774 asm volatile (
785 "mov r0, #0 \n" 775 "mov r0, #0 \n"
786 "mcr p15, 0, r0, c7, c0, 4 \n" /* Wait for interrupt */ 776 "mcr p15, 0, r0, c7, c0, 4 \n" /* Wait for interrupt */
787 "mrs r0, cpsr \n" /* Unmask IRQ at core level */
788 "bic r0, r0, #0x80 \n"
789 "msr cpsr_c, r0 \n"
790 : : : "r0" 777 : : : "r0"
791 ); 778 );
779 enable_irq();
792} 780}
793#elif CONFIG_CPU == IMX31L 781#elif CONFIG_CPU == IMX31L
794static inline void core_sleep(void) 782static inline void core_sleep(void)
@@ -796,17 +784,15 @@ static inline void core_sleep(void)
796 asm volatile ( 784 asm volatile (
797 "mov r0, #0 \n" 785 "mov r0, #0 \n"
798 "mcr p15, 0, r0, c7, c0, 4 \n" /* Wait for interrupt */ 786 "mcr p15, 0, r0, c7, c0, 4 \n" /* Wait for interrupt */
799 "mrs r0, cpsr \n" /* Unmask IRQ at core level */
800 "bic r0, r0, #0x80 \n"
801 "msr cpsr_c, r0 \n"
802 : : : "r0" 787 : : : "r0"
803 ); 788 );
789 enable_irq();
804} 790}
805#else 791#else
806static inline void core_sleep(void) 792static inline void core_sleep(void)
807{ 793{
808 #warning core_sleep not implemented, battery life will be decreased 794 #warning core_sleep not implemented, battery life will be decreased
809 set_irq_level(0); 795 enable_irq();
810} 796}
811#endif /* CONFIG_CPU == */ 797#endif /* CONFIG_CPU == */
812 798
@@ -1706,14 +1692,14 @@ void check_tmo_threads(void)
1706 while (next != NULL) 1692 while (next != NULL)
1707 { 1693 {
1708 /* Check sleeping threads. Allow interrupts between checks. */ 1694 /* Check sleeping threads. Allow interrupts between checks. */
1709 set_irq_level(0); 1695 enable_irq();
1710 1696
1711 struct thread_entry *curr = next; 1697 struct thread_entry *curr = next;
1712 1698
1713 next = curr->tmo.next; 1699 next = curr->tmo.next;
1714 1700
1715 /* Lock thread slot against explicit wakeup */ 1701 /* Lock thread slot against explicit wakeup */
1716 set_irq_level(HIGHEST_IRQ_LEVEL); 1702 disable_irq();
1717 LOCK_THREAD(curr); 1703 LOCK_THREAD(curr);
1718 1704
1719 unsigned state = curr->state; 1705 unsigned state = curr->state;
@@ -1956,7 +1942,7 @@ void switch_thread(void)
1956 check_tmo_threads(); 1942 check_tmo_threads();
1957 } 1943 }
1958 1944
1959 set_irq_level(HIGHEST_IRQ_LEVEL); 1945 disable_irq();
1960 RTR_LOCK(core); 1946 RTR_LOCK(core);
1961 1947
1962 thread = cores[core].running; 1948 thread = cores[core].running;
@@ -2018,7 +2004,7 @@ void switch_thread(void)
2018#endif /* HAVE_PRIORITY_SCHEDULING */ 2004#endif /* HAVE_PRIORITY_SCHEDULING */
2019 2005
2020 RTR_UNLOCK(core); 2006 RTR_UNLOCK(core);
2021 set_irq_level(0); 2007 enable_irq();
2022 break; 2008 break;
2023 } 2009 }
2024 } 2010 }
@@ -2212,7 +2198,7 @@ unsigned int thread_queue_wake(struct thread_entry **list)
2212static struct thread_entry * find_empty_thread_slot(void) 2198static struct thread_entry * find_empty_thread_slot(void)
2213{ 2199{
2214 /* Any slot could be on an interrupt-accessible list */ 2200 /* Any slot could be on an interrupt-accessible list */
2215 IF_COP( int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); ) 2201 IF_COP( int oldlevel = disable_irq_save(); )
2216 struct thread_entry *thread = NULL; 2202 struct thread_entry *thread = NULL;
2217 int n; 2203 int n;
2218 2204
@@ -2233,7 +2219,7 @@ static struct thread_entry * find_empty_thread_slot(void)
2233 UNLOCK_THREAD(t); 2219 UNLOCK_THREAD(t);
2234 } 2220 }
2235 2221
2236 IF_COP( set_irq_level(oldlevel); ) /* Reenable interrups - this slot is 2222 IF_COP( restore_irq(oldlevel); ) /* Reenable interrups - this slot is
2237 not accesible to them yet */ 2223 not accesible to them yet */
2238 return thread; 2224 return thread;
2239} 2225}
@@ -2247,7 +2233,7 @@ static struct thread_entry * find_empty_thread_slot(void)
2247void core_idle(void) 2233void core_idle(void)
2248{ 2234{
2249 IF_COP( const unsigned int core = CURRENT_CORE; ) 2235 IF_COP( const unsigned int core = CURRENT_CORE; )
2250 set_irq_level(HIGHEST_IRQ_LEVEL); 2236 disable_irq();
2251 core_sleep(IF_COP(core)); 2237 core_sleep(IF_COP(core));
2252} 2238}
2253 2239
@@ -2277,7 +2263,7 @@ struct thread_entry*
2277 return NULL; 2263 return NULL;
2278 } 2264 }
2279 2265
2280 oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); 2266 oldlevel = disable_irq_save();
2281 2267
2282 /* Munge the stack to make it easy to spot stack overflows */ 2268 /* Munge the stack to make it easy to spot stack overflows */
2283 stackptr = ALIGN_UP((uintptr_t)stack, sizeof (uintptr_t)); 2269 stackptr = ALIGN_UP((uintptr_t)stack, sizeof (uintptr_t));
@@ -2338,7 +2324,7 @@ struct thread_entry*
2338 2324
2339 UNLOCK_THREAD(thread); 2325 UNLOCK_THREAD(thread);
2340 2326
2341 set_irq_level(oldlevel); 2327 restore_irq(oldlevel);
2342 2328
2343 return thread; 2329 return thread;
2344} 2330}
@@ -2394,7 +2380,7 @@ void thread_wait(struct thread_entry *thread)
2394 IF_COP( current->obj_cl = &thread->waiter_cl; ) 2380 IF_COP( current->obj_cl = &thread->waiter_cl; )
2395 current->bqp = &thread->queue; 2381 current->bqp = &thread->queue;
2396 2382
2397 set_irq_level(HIGHEST_IRQ_LEVEL); 2383 disable_irq();
2398 block_thread(current); 2384 block_thread(current);
2399 2385
2400 corelock_unlock(&thread->waiter_cl); 2386 corelock_unlock(&thread->waiter_cl);
@@ -2418,7 +2404,7 @@ void thread_exit(void)
2418 /* Cancel CPU boost if any */ 2404 /* Cancel CPU boost if any */
2419 cancel_cpu_boost(); 2405 cancel_cpu_boost();
2420 2406
2421 set_irq_level(HIGHEST_IRQ_LEVEL); 2407 disable_irq();
2422 2408
2423 corelock_lock(&current->waiter_cl); 2409 corelock_lock(&current->waiter_cl);
2424 LOCK_THREAD(current); 2410 LOCK_THREAD(current);
@@ -2503,7 +2489,7 @@ void remove_thread(struct thread_entry *thread)
2503 if (thread == current) 2489 if (thread == current)
2504 thread_exit(); /* Current thread - do normal exit */ 2490 thread_exit(); /* Current thread - do normal exit */
2505 2491
2506 oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); 2492 oldlevel = disable_irq_save();
2507 2493
2508 corelock_lock(&thread->waiter_cl); 2494 corelock_lock(&thread->waiter_cl);
2509 LOCK_THREAD(thread); 2495 LOCK_THREAD(thread);
@@ -2521,7 +2507,7 @@ void remove_thread(struct thread_entry *thread)
2521 /* Thread being killed - become a waiter */ 2507 /* Thread being killed - become a waiter */
2522 UNLOCK_THREAD(thread); 2508 UNLOCK_THREAD(thread);
2523 corelock_unlock(&thread->waiter_cl); 2509 corelock_unlock(&thread->waiter_cl);
2524 set_irq_level(oldlevel); 2510 restore_irq(oldlevel);
2525 thread_wait(thread); 2511 thread_wait(thread);
2526 return; 2512 return;
2527 } 2513 }
@@ -2543,11 +2529,11 @@ void remove_thread(struct thread_entry *thread)
2543 corelock_unlock(&thread->waiter_cl); 2529 corelock_unlock(&thread->waiter_cl);
2544 2530
2545 UNLOCK_THREAD(thread); 2531 UNLOCK_THREAD(thread);
2546 set_irq_level(oldlevel); 2532 restore_irq(oldlevel);
2547 2533
2548 old_core = switch_core(new_core); 2534 old_core = switch_core(new_core);
2549 2535
2550 oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); 2536 oldlevel = disable_irq_save();
2551 2537
2552 corelock_lock(&thread->waiter_cl); 2538 corelock_lock(&thread->waiter_cl);
2553 LOCK_THREAD(thread); 2539 LOCK_THREAD(thread);
@@ -2643,7 +2629,7 @@ thread_killed: /* Thread was already killed */
2643 /* Removal complete - safe to unlock and reenable interrupts */ 2629 /* Removal complete - safe to unlock and reenable interrupts */
2644 corelock_unlock(&thread->waiter_cl); 2630 corelock_unlock(&thread->waiter_cl);
2645 UNLOCK_THREAD(thread); 2631 UNLOCK_THREAD(thread);
2646 set_irq_level(oldlevel); 2632 restore_irq(oldlevel);
2647 2633
2648#if NUM_CORES > 1 2634#if NUM_CORES > 1
2649 if (old_core < NUM_CORES) 2635 if (old_core < NUM_CORES)
@@ -2675,7 +2661,7 @@ int thread_set_priority(struct thread_entry *thread, int priority)
2675 2661
2676 /* Thread could be on any list and therefore on an interrupt accessible 2662 /* Thread could be on any list and therefore on an interrupt accessible
2677 one - disable interrupts */ 2663 one - disable interrupts */
2678 int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); 2664 int oldlevel = disable_irq_save();
2679 2665
2680 LOCK_THREAD(thread); 2666 LOCK_THREAD(thread);
2681 2667
@@ -2788,7 +2774,7 @@ int thread_set_priority(struct thread_entry *thread, int priority)
2788 2774
2789 UNLOCK_THREAD(thread); 2775 UNLOCK_THREAD(thread);
2790 2776
2791 set_irq_level(oldlevel); 2777 restore_irq(oldlevel);
2792 2778
2793 return old_base_priority; 2779 return old_base_priority;
2794} 2780}
@@ -2815,14 +2801,14 @@ int thread_get_priority(struct thread_entry *thread)
2815 */ 2801 */
2816void thread_thaw(struct thread_entry *thread) 2802void thread_thaw(struct thread_entry *thread)
2817{ 2803{
2818 int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); 2804 int oldlevel = disable_irq_save();
2819 LOCK_THREAD(thread); 2805 LOCK_THREAD(thread);
2820 2806
2821 if (thread->state == STATE_FROZEN) 2807 if (thread->state == STATE_FROZEN)
2822 core_schedule_wakeup(thread); 2808 core_schedule_wakeup(thread);
2823 2809
2824 UNLOCK_THREAD(thread); 2810 UNLOCK_THREAD(thread);
2825 set_irq_level(oldlevel); 2811 restore_irq(oldlevel);
2826} 2812}
2827 2813
2828/*--------------------------------------------------------------------------- 2814/*---------------------------------------------------------------------------
@@ -2850,14 +2836,14 @@ unsigned int switch_core(unsigned int new_core)
2850 return core; 2836 return core;
2851 } 2837 }
2852 2838
2853 int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL); 2839 int oldlevel = disable_irq_save();
2854 LOCK_THREAD(current); 2840 LOCK_THREAD(current);
2855 2841
2856 if (current->name == THREAD_DESTRUCT) 2842 if (current->name == THREAD_DESTRUCT)
2857 { 2843 {
2858 /* Thread being killed - deactivate and let process complete */ 2844 /* Thread being killed - deactivate and let process complete */
2859 UNLOCK_THREAD(current); 2845 UNLOCK_THREAD(current);
2860 set_irq_level(oldlevel); 2846 restore_irq(oldlevel);
2861 thread_wait(current); 2847 thread_wait(current);
2862 /* Should never be reached */ 2848 /* Should never be reached */
2863 THREAD_PANICF("switch_core->D:*R", current); 2849 THREAD_PANICF("switch_core->D:*R", current);
diff --git a/firmware/usb.c b/firmware/usb.c
index 2971ab7041..c33b62f244 100644
--- a/firmware/usb.c
+++ b/firmware/usb.c
@@ -568,10 +568,10 @@ bool usb_charging_enable(bool on)
568#ifdef IRIVER_H300_SERIES 568#ifdef IRIVER_H300_SERIES
569 int irqlevel; 569 int irqlevel;
570 logf("usb_charging_enable(%s)\n", on ? "on" : "off" ); 570 logf("usb_charging_enable(%s)\n", on ? "on" : "off" );
571 irqlevel = set_irq_level(HIGHEST_IRQ_LEVEL); 571 irqlevel = disable_irq_save();
572 pcf50606_set_usb_charging(on); 572 pcf50606_set_usb_charging(on);
573 rc = on; 573 rc = on;
574 (void)set_irq_level(irqlevel); 574 restore_irq(irqlevel);
575#else 575#else
576 /* TODO: implement it for other targets... */ 576 /* TODO: implement it for other targets... */
577 (void)on; 577 (void)on;