blob: 54a53f3607eb37fff7870184e4c0e9e12727a490 [file] [log] [blame]
Björn Stenberg1acfd6b2002-04-21 22:06:12 +00001/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
Nicolas Pennequin396aeaf2009-03-23 17:08:46 +000010 * Copyright (C) 2002 by Björn Stenberg
Björn Stenberg1acfd6b2002-04-21 22:06:12 +000011 *
Daniel Stenberg2acc0ac2008-06-28 18:10:04 +000012 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
Björn Stenberg1acfd6b2002-04-21 22:06:12 +000016 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#ifndef _KERNEL_H_
22#define _KERNEL_H_
23
Björn Stenberg29f80282002-05-23 09:22:07 +000024#include <stdbool.h>
Michael Sevakis4b902672006-12-19 16:50:07 +000025#include <inttypes.h>
Dave Chapman77372d12005-11-07 23:07:19 +000026#include "config.h"
Björn Stenberg29f80282002-05-23 09:22:07 +000027
Michael Sevakisa9b2fb52007-10-16 01:25:17 +000028#include "thread.h"
29
Björn Stenberg1acfd6b2002-04-21 22:06:12 +000030/* wrap-safe macros for tick comparison */
31#define TIME_AFTER(a,b) ((long)(b) - (long)(a) < 0)
32#define TIME_BEFORE(a,b) TIME_AFTER(b,a)
33
34#define HZ 100 /* number of ticks per second */
35
Jens Arnoldfed2c562005-11-23 08:51:48 +000036#define MAX_NUM_TICK_TASKS 8
Linus Nielsen Feltzing150c5a72002-06-04 12:25:53 +000037
Michael Sevakisa9b2fb52007-10-16 01:25:17 +000038#define MAX_NUM_QUEUES 32
Linus Nielsen Feltzingbd2561d2002-04-29 14:25:44 +000039#define QUEUE_LENGTH 16 /* MUST be a power of 2 */
40#define QUEUE_LENGTH_MASK (QUEUE_LENGTH - 1)
41
Michael Sevakis58fc2792007-07-28 08:12:05 +000042/* System defined message ID's - |sign bit = 1|class|id| */
43/* Event class list */
44#define SYS_EVENT_CLS_QUEUE 0
45#define SYS_EVENT_CLS_USB 1
46#define SYS_EVENT_CLS_POWER 2
47#define SYS_EVENT_CLS_FILESYS 3
48#define SYS_EVENT_CLS_PLUG 4
Michael Sevakis0107dfc2007-09-09 01:59:07 +000049#define SYS_EVENT_CLS_MISC 5
Michael Sevakisadf2e4c2008-05-28 10:17:16 +000050#define SYS_EVENT_CLS_PRIVATE 7 /* For use inside plugins */
Michael Sevakis58fc2792007-07-28 08:12:05 +000051/* make sure SYS_EVENT_CLS_BITS has enough range */
52
Michael Sevakis5832b592007-07-28 08:45:57 +000053/* Bit 31->|S|c...c|i...i| */
54#define SYS_EVENT ((long)(int)(1 << 31))
Michael Sevakis58fc2792007-07-28 08:12:05 +000055#define SYS_EVENT_CLS_BITS (3)
Michael Sevakis5832b592007-07-28 08:45:57 +000056#define SYS_EVENT_CLS_SHIFT (31-SYS_EVENT_CLS_BITS)
Michael Sevakis58fc2792007-07-28 08:12:05 +000057#define SYS_EVENT_CLS_MASK (((1l << SYS_EVENT_CLS_BITS)-1) << SYS_EVENT_SHIFT)
58#define MAKE_SYS_EVENT(cls, id) (SYS_EVENT | ((long)(cls) << SYS_EVENT_CLS_SHIFT) | (long)(id))
59/* Macros for extracting codes */
60#define SYS_EVENT_CLS(e) (((e) & SYS_EVENT_CLS_MASK) >> SYS_EVENT_SHIFT)
61#define SYS_EVENT_ID(e) ((e) & ~(SYS_EVENT|SYS_EVENT_CLS_MASK))
62
63#define SYS_TIMEOUT MAKE_SYS_EVENT(SYS_EVENT_CLS_QUEUE, 0)
64#define SYS_USB_CONNECTED MAKE_SYS_EVENT(SYS_EVENT_CLS_USB, 0)
65#define SYS_USB_CONNECTED_ACK MAKE_SYS_EVENT(SYS_EVENT_CLS_USB, 1)
66#define SYS_USB_DISCONNECTED MAKE_SYS_EVENT(SYS_EVENT_CLS_USB, 2)
Frank Gevaertsb6a1af22009-02-28 14:47:18 +000067#define SYS_USB_LUN_LOCKED MAKE_SYS_EVENT(SYS_EVENT_CLS_USB, 4)
Frank Gevaerts3b141d92009-02-28 16:25:07 +000068#define SYS_USB_READ_DATA MAKE_SYS_EVENT(SYS_EVENT_CLS_USB, 5)
69#define SYS_USB_WRITE_DATA MAKE_SYS_EVENT(SYS_EVENT_CLS_USB, 6)
Michael Sevakis58fc2792007-07-28 08:12:05 +000070#define SYS_POWEROFF MAKE_SYS_EVENT(SYS_EVENT_CLS_POWER, 0)
71#define SYS_CHARGER_CONNECTED MAKE_SYS_EVENT(SYS_EVENT_CLS_POWER, 1)
72#define SYS_CHARGER_DISCONNECTED MAKE_SYS_EVENT(SYS_EVENT_CLS_POWER, 2)
Stéphane Doyonda932992007-11-03 05:00:49 +000073#define SYS_BATTERY_UPDATE MAKE_SYS_EVENT(SYS_EVENT_CLS_POWER, 3)
Michael Sevakis58fc2792007-07-28 08:12:05 +000074#define SYS_FS_CHANGED MAKE_SYS_EVENT(SYS_EVENT_CLS_FILESYS, 0)
75#define SYS_HOTSWAP_INSERTED MAKE_SYS_EVENT(SYS_EVENT_CLS_PLUG, 0)
76#define SYS_HOTSWAP_EXTRACTED MAKE_SYS_EVENT(SYS_EVENT_CLS_PLUG, 1)
77#define SYS_PHONE_PLUGGED MAKE_SYS_EVENT(SYS_EVENT_CLS_PLUG, 2)
78#define SYS_PHONE_UNPLUGGED MAKE_SYS_EVENT(SYS_EVENT_CLS_PLUG, 3)
79#define SYS_REMOTE_PLUGGED MAKE_SYS_EVENT(SYS_EVENT_CLS_PLUG, 4)
80#define SYS_REMOTE_UNPLUGGED MAKE_SYS_EVENT(SYS_EVENT_CLS_PLUG, 5)
Jens Arnold3e67e3b2009-02-20 17:13:08 +000081#define SYS_CAR_ADAPTER_RESUME MAKE_SYS_EVENT(SYS_EVENT_CLS_MISC, 0)
82#define SYS_IAP_PERIODIC MAKE_SYS_EVENT(SYS_EVENT_CLS_MISC, 1)
83#define SYS_IAP_HANDLEPKT MAKE_SYS_EVENT(SYS_EVENT_CLS_MISC, 2)
Thomas Martitzca4439f2010-08-07 21:30:22 +000084#define SYS_CALL_INCOMING MAKE_SYS_EVENT(SYS_EVENT_CLS_MISC, 3)
85#define SYS_CALL_HUNG_UP MAKE_SYS_EVENT(SYS_EVENT_CLS_MISC, 4)
Björn Stenberge50cc0e2011-03-14 12:25:48 +000086#define SYS_VOLUME_CHANGED MAKE_SYS_EVENT(SYS_EVENT_CLS_MISC, 5)
Jens Arnoldf5bdf692004-10-10 00:35:19 +000087
Michael Sevakis27cf6772008-03-25 02:34:12 +000088#define IS_SYSEVENT(ev) ((ev & SYS_EVENT) == SYS_EVENT)
Michael Sevakisc537d592011-04-27 03:08:23 +000089#define EVENT_RESERVED (~0)
Michael Sevakis27cf6772008-03-25 02:34:12 +000090
Michael Sevakisbc192c92008-03-30 04:59:51 +000091#ifndef TIMEOUT_BLOCK
92#define TIMEOUT_BLOCK -1
93#define TIMEOUT_NOBLOCK 0
94#endif
95
Michael Sevakisa9b2fb52007-10-16 01:25:17 +000096struct queue_event
Linus Nielsen Feltzingbd2561d2002-04-29 14:25:44 +000097{
Michael Sevakis4b902672006-12-19 16:50:07 +000098 long id;
99 intptr_t data;
Linus Nielsen Feltzingbd2561d2002-04-29 14:25:44 +0000100};
101
Michael Sevakis43c15922006-12-16 18:35:12 +0000102#ifdef HAVE_EXTENDED_MESSAGING_AND_NAME
Michael Sevakis43c15922006-12-16 18:35:12 +0000103struct queue_sender_list
104{
105 /* If non-NULL, there is a thread waiting for the corresponding event */
Michael Sevakis0caf3b82007-03-21 22:58:53 +0000106 /* Must be statically allocated to put in non-cached ram. */
Michael Sevakis27cf6772008-03-25 02:34:12 +0000107 struct thread_entry *senders[QUEUE_LENGTH]; /* message->thread map */
108 struct thread_entry *list; /* list of senders in map */
Michael Sevakis43c15922006-12-16 18:35:12 +0000109 /* Send info for last message dequeued or NULL if replied or not sent */
Michael Sevakis7b4eb442010-12-27 10:05:09 +0000110 struct thread_entry * volatile curr_sender;
Michael Sevakis27cf6772008-03-25 02:34:12 +0000111#ifdef HAVE_PRIORITY_SCHEDULING
112 struct blocker blocker;
113#endif
Michael Sevakis43c15922006-12-16 18:35:12 +0000114};
115#endif /* HAVE_EXTENDED_MESSAGING_AND_NAME */
116
Michael Sevakis27cf6772008-03-25 02:34:12 +0000117#ifdef HAVE_PRIORITY_SCHEDULING
118#define QUEUE_GET_THREAD(q) \
119 (((q)->send == NULL) ? NULL : (q)->send->blocker.thread)
120#else
121/* Queue without priority enabled have no owner provision _at this time_ */
122#define QUEUE_GET_THREAD(q) \
123 (NULL)
124#endif
125
Linus Nielsen Feltzingbd2561d2002-04-29 14:25:44 +0000126struct event_queue
127{
Michael Sevakis27cf6772008-03-25 02:34:12 +0000128 struct thread_entry *queue; /* waiter list */
Michael Sevakisa9b2fb52007-10-16 01:25:17 +0000129 struct queue_event events[QUEUE_LENGTH]; /* list of events */
Michael Sevakis7b4eb442010-12-27 10:05:09 +0000130 unsigned int volatile read; /* head of queue */
131 unsigned int volatile write; /* tail of queue */
Michael Sevakis8b497002006-12-16 18:41:45 +0000132#ifdef HAVE_EXTENDED_MESSAGING_AND_NAME
Michael Sevakis7b4eb442010-12-27 10:05:09 +0000133 struct queue_sender_list * volatile send; /* list of threads waiting for
Michael Sevakis27cf6772008-03-25 02:34:12 +0000134 reply to an event */
135#ifdef HAVE_PRIORITY_SCHEDULING
136 struct blocker *blocker_p; /* priority inheritance info
137 for sync message senders */
Michael Sevakisa9b2fb52007-10-16 01:25:17 +0000138#endif
Michael Sevakis8b497002006-12-16 18:41:45 +0000139#endif
Michael Sevakis27cf6772008-03-25 02:34:12 +0000140 IF_COP( struct corelock cl; ) /* multiprocessor sync */
Linus Nielsen Feltzingbd2561d2002-04-29 14:25:44 +0000141};
142
Linus Nielsen Feltzing73613402002-05-16 20:57:32 +0000143struct mutex
144{
Michael Sevakis27cf6772008-03-25 02:34:12 +0000145 struct thread_entry *queue; /* waiter list */
Michael Sevakisf387cde2010-12-26 05:59:39 +0000146 int recursion; /* lock owner recursion count */
Michael Sevakis27cf6772008-03-25 02:34:12 +0000147#ifdef HAVE_PRIORITY_SCHEDULING
148 struct blocker blocker; /* priority inheritance info
149 for waiters */
150 bool no_preempt; /* don't allow higher-priority thread
151 to be scheduled even if woken */
152#else
Michael Sevakisf387cde2010-12-26 05:59:39 +0000153 struct thread_entry *thread; /* Indicates owner thread - an owner
154 implies a locked state - same goes
155 for priority scheduling
156 (in blocker struct for that) */
Michael Sevakisa9b2fb52007-10-16 01:25:17 +0000157#endif
Michael Sevakis27cf6772008-03-25 02:34:12 +0000158 IF_COP( struct corelock cl; ) /* multiprocessor sync */
Linus Nielsen Feltzing73613402002-05-16 20:57:32 +0000159};
160
Michael Sevakisa9b2fb52007-10-16 01:25:17 +0000161#ifdef HAVE_SEMAPHORE_OBJECTS
162struct semaphore
163{
Michael Sevakis27cf6772008-03-25 02:34:12 +0000164 struct thread_entry *queue; /* Waiter list */
Michael Sevakis12375d12011-03-02 08:49:38 +0000165 int volatile count; /* # of waits remaining before unsignaled */
Michael Sevakis27cf6772008-03-25 02:34:12 +0000166 int max; /* maximum # of waits to remain signaled */
167 IF_COP( struct corelock cl; ) /* multiprocessor sync */
Michael Sevakisa9b2fb52007-10-16 01:25:17 +0000168};
169#endif
170
Björn Stenberg1acfd6b2002-04-21 22:06:12 +0000171/* global tick variable */
Michael Sevakis3a112772011-01-15 08:19:30 +0000172#if defined(CPU_PP) && defined(BOOTLOADER) && \
173 !defined(HAVE_BOOTLOADER_USB_MODE)
174/* We don't enable interrupts in the PP bootloader unless USB mode is
175 enabled for it, so we need to fake the current_tick variable */
Brandon Low780e8dd2006-03-05 18:40:51 +0000176#define current_tick (signed)(USEC_TIMER/10000)
Michael Sevakis623cd1c2008-10-27 17:18:01 +0000177
178static inline void call_tick_tasks(void)
179{
180}
Dave Chapmancb7e6952006-01-05 17:02:48 +0000181#else
Michael Sevakis6bba70b2007-06-25 20:46:54 +0000182extern volatile long current_tick;
Michael Sevakis623cd1c2008-10-27 17:18:01 +0000183
184/* inline helper for implementing target interrupt handler */
185static inline void call_tick_tasks(void)
186{
187 extern void (*tick_funcs[MAX_NUM_TICK_TASKS+1])(void);
Michael Sevakis580d91f2009-01-21 02:44:20 +0000188 void (**p)(void) = tick_funcs;
189 void (*fn)(void);
Michael Sevakis623cd1c2008-10-27 17:18:01 +0000190
191 current_tick++;
192
Michael Sevakis580d91f2009-01-21 02:44:20 +0000193 for(fn = *p; fn != NULL; fn = *(++p))
194 {
195 fn();
196 }
Michael Sevakis623cd1c2008-10-27 17:18:01 +0000197}
Dave Chapmancb7e6952006-01-05 17:02:48 +0000198#endif
Björn Stenberg1acfd6b2002-04-21 22:06:12 +0000199
200/* kernel functions */
Thomas Martitzf8edc322010-03-03 23:20:32 +0000201extern void kernel_init(void) INIT_ATTR;
Björn Stenberg1acfd6b2002-04-21 22:06:12 +0000202extern void yield(void);
Thomas Martitz6eaab4d2010-09-01 21:29:34 +0000203extern unsigned sleep(unsigned ticks);
Linus Nielsen Feltzingba396f02002-05-06 19:26:56 +0000204int tick_add_task(void (*f)(void));
205int tick_remove_task(void (*f)(void));
Rafaël Carré435e08e2010-05-27 12:00:29 +0000206extern void tick_start(unsigned int interval_in_ms) INIT_ATTR;
Björn Stenberg1acfd6b2002-04-21 22:06:12 +0000207
Rob Purchase75b27ea2009-07-14 20:04:26 +0000208#ifdef INCLUDE_TIMEOUT_API
Michael Sevakise64f7e32007-07-29 04:49:19 +0000209struct timeout;
210
211/* timeout callback type
212 * tmo - pointer to struct timeout associated with event
Michael Sevakis580d91f2009-01-21 02:44:20 +0000213 * return next interval or <= 0 to stop event
Michael Sevakise64f7e32007-07-29 04:49:19 +0000214 */
Michael Sevakis580d91f2009-01-21 02:44:20 +0000215#define MAX_NUM_TIMEOUTS 8
216typedef int (* timeout_cb_type)(struct timeout *tmo);
Michael Sevakise64f7e32007-07-29 04:49:19 +0000217
218struct timeout
219{
Michael Sevakise64f7e32007-07-29 04:49:19 +0000220 timeout_cb_type callback;/* callback - returning false cancels */
Michael Sevakise64f7e32007-07-29 04:49:19 +0000221 intptr_t data; /* data passed to callback */
Michael Sevakis580d91f2009-01-21 02:44:20 +0000222 long expires; /* expiration tick */
Michael Sevakise64f7e32007-07-29 04:49:19 +0000223};
224
225void timeout_register(struct timeout *tmo, timeout_cb_type callback,
226 int ticks, intptr_t data);
227void timeout_cancel(struct timeout *tmo);
Rob Purchase75b27ea2009-07-14 20:04:26 +0000228#endif /* INCLUDE_TIMEOUT_API */
Michael Sevakise64f7e32007-07-29 04:49:19 +0000229
Michael Sevakisa9b2fb52007-10-16 01:25:17 +0000230#define STATE_NONSIGNALED 0
231#define STATE_SIGNALED 1
232
Michael Sevakis3c8d93e2008-04-01 03:55:02 +0000233#define OBJ_WAIT_TIMEDOUT (-1)
234#define OBJ_WAIT_FAILED 0
235#define OBJ_WAIT_SUCCEEDED 1
Michael Sevakisa9b2fb52007-10-16 01:25:17 +0000236
Miika Pekkarinena85044b2006-09-16 16:18:11 +0000237extern void queue_init(struct event_queue *q, bool register_queue);
Linus Nielsen Feltzing765e0f82006-01-23 10:53:47 +0000238extern void queue_delete(struct event_queue *q);
Michael Sevakisa9b2fb52007-10-16 01:25:17 +0000239extern void queue_wait(struct event_queue *q, struct queue_event *ev);
240extern void queue_wait_w_tmo(struct event_queue *q, struct queue_event *ev,
241 int ticks);
Michael Sevakis4b902672006-12-19 16:50:07 +0000242extern void queue_post(struct event_queue *q, long id, intptr_t data);
Michael Sevakis43c15922006-12-16 18:35:12 +0000243#ifdef HAVE_EXTENDED_MESSAGING_AND_NAME
Michael Sevakis27cf6772008-03-25 02:34:12 +0000244extern void queue_enable_queue_send(struct event_queue *q,
245 struct queue_sender_list *send,
Michael Sevakis8cfbd362008-12-10 08:57:10 +0000246 unsigned int owner_id);
Michael Sevakis4b902672006-12-19 16:50:07 +0000247extern intptr_t queue_send(struct event_queue *q, long id, intptr_t data);
248extern void queue_reply(struct event_queue *q, intptr_t retval);
Michael Sevakis43c15922006-12-16 18:35:12 +0000249extern bool queue_in_queue_send(struct event_queue *q);
250#endif /* HAVE_EXTENDED_MESSAGING_AND_NAME */
Jens Arnoldc76c5682004-08-16 23:37:23 +0000251extern bool queue_empty(const struct event_queue* q);
Nicolas Pennequin1839edf2007-10-27 18:08:18 +0000252extern bool queue_peek(struct event_queue *q, struct queue_event *ev);
Michael Sevakisc537d592011-04-27 03:08:23 +0000253
254#define QPEEK_FILTER_COUNT_MASK (0xffu) /* 0x00=1 filter, 0xff=256 filters */
255#define QPEEK_FILTER_HEAD_ONLY (1u << 8) /* Ignored if no filters */
256#define QPEEK_REMOVE_EVENTS (1u << 9) /* Remove or discard events */
257extern bool queue_peek_ex(struct event_queue *q,
258 struct queue_event *ev,
259 unsigned int flags,
260 const long (*filters)[2]);
261
Michael Sevakis43c15922006-12-16 18:35:12 +0000262extern void queue_clear(struct event_queue* q);
Linus Nielsen Feltzing4950b552006-10-19 11:43:13 +0000263extern void queue_remove_from_head(struct event_queue *q, long id);
Miika Pekkarinen2eefb5a2007-03-11 10:52:36 +0000264extern int queue_count(const struct event_queue *q);
Michael Sevakis4b902672006-12-19 16:50:07 +0000265extern int queue_broadcast(long id, intptr_t data);
Björn Stenberg1acfd6b2002-04-21 22:06:12 +0000266
Linus Nielsen Feltzing73613402002-05-16 20:57:32 +0000267extern void mutex_init(struct mutex *m);
268extern void mutex_lock(struct mutex *m);
269extern void mutex_unlock(struct mutex *m);
Michael Sevakis27cf6772008-03-25 02:34:12 +0000270#ifdef HAVE_PRIORITY_SCHEDULING
Michael Sevakisf387cde2010-12-26 05:59:39 +0000271/* Deprecated temporary function to disable mutex preempting a thread on
272 * unlock - firmware/drivers/fat.c and a couple places in apps/buffering.c -
273 * reliance on it is a bug! */
Michael Sevakis27cf6772008-03-25 02:34:12 +0000274static inline void mutex_set_preempt(struct mutex *m, bool preempt)
275 { m->no_preempt = !preempt; }
Michael Sevakisf387cde2010-12-26 05:59:39 +0000276#else
277/* Deprecated but needed for now - firmware/drivers/ata_mmc.c */
278static inline bool mutex_test(const struct mutex *m)
279 { return m->thread != NULL; }
280#endif /* HAVE_PRIORITY_SCHEDULING */
281
Michael Sevakisa9b2fb52007-10-16 01:25:17 +0000282#ifdef HAVE_SEMAPHORE_OBJECTS
283extern void semaphore_init(struct semaphore *s, int max, int start);
Michael Sevakis12375d12011-03-02 08:49:38 +0000284extern int semaphore_wait(struct semaphore *s, int timeout);
Michael Sevakisa9b2fb52007-10-16 01:25:17 +0000285extern void semaphore_release(struct semaphore *s);
286#endif /* HAVE_SEMAPHORE_OBJECTS */
Linus Nielsen Feltzingce726be2005-04-06 13:05:06 +0000287
Michael Sevakisa9b2fb52007-10-16 01:25:17 +0000288#endif /* _KERNEL_H_ */