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 ****************************************************************************/
27 long current_tick
= 0;
29 void (*tick_funcs
[MAX_NUM_TICK_TASKS
])(void);
31 static void tick_start(unsigned int interval_in_ms
);
33 /* This array holds all queues that are initiated. It is used for broadcast. */
34 static struct event_queue
*all_queues
[32];
35 static int num_queues
;
37 void sleep(int ticks
) __attribute__ ((section(".icode")));
38 void queue_wait(struct event_queue
*q
, struct event
*ev
) __attribute__ ((section(".icode")));;
40 /****************************************************************************
41 * Standard kernel stuff
42 ****************************************************************************/
43 void kernel_init(void)
45 /* Init the threading API */
48 memset(tick_funcs
, 0, sizeof(tick_funcs
));
51 memset(all_queues
, 0, sizeof(all_queues
));
58 /* Always sleep at least 1 tick */
59 int timeout
= current_tick
+ ticks
+ 1;
61 while (TIME_BEFORE( current_tick
, timeout
)) {
71 /****************************************************************************
72 * Interrupt level setting
73 ****************************************************************************/
74 int set_irq_level(int level
)
77 /* Read the old level and set the new one */
78 asm volatile ("stc sr, %0" : "=r" (i
));
79 asm volatile ("ldc %0, sr" : : "r" (level
<< 4));
80 return (i
>> 4) & 0x0f;
83 /****************************************************************************
84 * Queue handling stuff
85 ****************************************************************************/
86 void queue_init(struct event_queue
*q
)
91 /* Add it to the all_queues array */
92 all_queues
[num_queues
++] = q
;
95 void queue_wait(struct event_queue
*q
, struct event
*ev
)
97 while(q
->read
== q
->write
)
102 *ev
= q
->events
[(q
->read
++) & QUEUE_LENGTH_MASK
];
105 void queue_post(struct event_queue
*q
, int id
, void *data
)
110 oldlevel
= set_irq_level(15);
111 wr
= (q
->write
++) & QUEUE_LENGTH_MASK
;
113 q
->events
[wr
].id
= id
;
114 q
->events
[wr
].data
= data
;
115 set_irq_level(oldlevel
);
118 bool queue_empty(struct event_queue
* q
)
120 return ( q
->read
== q
->write
);
123 int queue_broadcast(int id
, void *data
)
127 for(i
= 0;i
< num_queues
;i
++)
129 queue_post(all_queues
[i
], id
, data
);
135 /****************************************************************************
137 ****************************************************************************/
138 static void tick_start(unsigned int interval_in_ms
)
142 count
= FREQ
/ 1000 / 8 * interval_in_ms
;
146 panicf("Error! The tick interval is too long (%d ms)\n",
151 /* We are using timer 0 */
153 TSTR
&= ~0x01; /* Stop the timer */
154 TSNC
&= ~0x01; /* No synchronization */
155 TMDR
&= ~0x01; /* Operate normally */
157 TCNT0
= 0; /* Start counting at 0 */
159 TCR0
= 0x23; /* Clear at GRA match, sysclock/8 */
161 /* Enable interrupt on level 1 */
162 IPRC
= (IPRC
& ~0x00f0) | 0x0010;
165 TIER0
= 0xf9; /* Enable GRA match interrupt */
167 TSTR
|= 0x01; /* Start timer 1 */
175 /* Run through the list of tick tasks */
176 for(i
= 0;i
< MAX_NUM_TICK_TASKS
;i
++)
189 int tick_add_task(void (*f
)(void))
192 int oldlevel
= set_irq_level(15);
194 /* Add a task if there is room */
195 for(i
= 0;i
< MAX_NUM_TICK_TASKS
;i
++)
197 if(tick_funcs
[i
] == NULL
)
200 set_irq_level(oldlevel
);
204 set_irq_level(oldlevel
);
205 panicf("Error! tick_add_task(): out of tasks");
209 int tick_remove_task(void (*f
)(void))
212 int oldlevel
= set_irq_level(15);
214 /* Remove a task if it is there */
215 for(i
= 0;i
< MAX_NUM_TICK_TASKS
;i
++)
217 if(tick_funcs
[i
] == f
)
219 tick_funcs
[i
] = NULL
;
220 set_irq_level(oldlevel
);
225 set_irq_level(oldlevel
);
229 /****************************************************************************
230 * Simple mutex functions
231 ****************************************************************************/
232 void mutex_init(struct mutex
*m
)
237 void mutex_lock(struct mutex
*m
)
239 /* Wait until the lock is open... */
247 void mutex_unlock(struct mutex
*m
)