summaryrefslogtreecommitdiffstats
path: root/firmware/export/kernel.h
blob: cd6a810bad65dcce476b5de6aff3821f8456d36b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/***************************************************************************
 *             __________               __   ___.
 *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
 *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
 *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
 *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
 *                     \/            \/     \/    \/            \/
 * $Id$
 *
 * Copyright (C) 2002 by Björn Stenberg
 *
 * All files in this archive are subject to the GNU General Public License.
 * See the file COPYING in the source tree root for full license agreement.
 *
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 * KIND, either express or implied.
 *
 ****************************************************************************/
#ifndef _KERNEL_H_
#define _KERNEL_H_

#include <stdbool.h>
#include <inttypes.h>
#include "config.h"

/* wrap-safe macros for tick comparison */
#define TIME_AFTER(a,b)         ((long)(b) - (long)(a) < 0)
#define TIME_BEFORE(a,b)        TIME_AFTER(b,a)

#define HZ      100 /* number of ticks per second */

#define MAX_NUM_TICK_TASKS 8

#define QUEUE_LENGTH 16 /* MUST be a power of 2 */
#define QUEUE_LENGTH_MASK (QUEUE_LENGTH - 1)

/* System defined message ID's, occupying the top 5 bits of the event ID */
#define SYS_EVENT                 (long)0x80000000 /* SYS events are negative */
#define SYS_USB_CONNECTED         ((SYS_EVENT | ((long)1 << 27)))
#define SYS_USB_CONNECTED_ACK     ((SYS_EVENT | ((long)2 << 27)))
#define SYS_USB_DISCONNECTED      ((SYS_EVENT | ((long)3 << 27)))
#define SYS_USB_DISCONNECTED_ACK  ((SYS_EVENT | ((long)4 << 27)))
#define SYS_TIMEOUT               ((SYS_EVENT | ((long)5 << 27)))
#define SYS_MMC_INSERTED          ((SYS_EVENT | ((long)6 << 27)))
#define SYS_MMC_EXTRACTED         ((SYS_EVENT | ((long)7 << 27)))
#define SYS_POWEROFF              ((SYS_EVENT | ((long)8 << 27)))
#define SYS_FS_CHANGED            ((SYS_EVENT | ((long)9 << 27)))
#define SYS_CHARGER_CONNECTED     ((SYS_EVENT | ((long)10 << 27)))
#define SYS_CHARGER_DISCONNECTED  ((SYS_EVENT | ((long)11 << 27)))
#define SYS_PHONE_PLUGGED         ((SYS_EVENT | ((long)12 << 27)))
#define SYS_PHONE_UNPLUGGED       ((SYS_EVENT | ((long)13 << 27)))

struct event
{
    long     id;
    intptr_t data;
};

#ifdef HAVE_EXTENDED_MESSAGING_AND_NAME
struct queue_sender
{
    struct thread_entry *thread;
    intptr_t             retval;
};

struct queue_sender_list
{
    /* If non-NULL, there is a thread waiting for the corresponding event */
    struct queue_sender *senders[QUEUE_LENGTH];
    /* Send info for last message dequeued or NULL if replied or not sent */
    struct queue_sender *curr_sender;
};
#endif /* HAVE_EXTENDED_MESSAGING_AND_NAME */

struct event_queue
{
    struct event events[QUEUE_LENGTH];
    struct thread_entry *thread;
    unsigned int read;
    unsigned int write;
#ifdef HAVE_EXTENDED_MESSAGING_AND_NAME
    struct queue_sender_list *send;
#endif
};

struct mutex
{
    uint32_t locked;
    struct thread_entry *thread;
};

/* global tick variable */
#if defined(CPU_PP) && defined(BOOTLOADER)
/* We don't enable interrupts in the iPod bootloader, so we need to fake
   the current_tick variable */
#define current_tick (signed)(USEC_TIMER/10000)
#else
extern long current_tick;
#endif

#ifdef SIMULATOR
#define sleep(x) sim_sleep(x)
#endif

/* kernel functions */
extern void kernel_init(void);
extern void yield(void);
extern void sleep(int ticks);
int tick_add_task(void (*f)(void));
int tick_remove_task(void (*f)(void));

extern void queue_init(struct event_queue *q, bool register_queue);
extern void queue_delete(struct event_queue *q);
extern void queue_wait(struct event_queue *q, struct event *ev);
extern void queue_wait_w_tmo(struct event_queue *q, struct event *ev, int ticks);
extern void queue_post(struct event_queue *q, long id, intptr_t data);
#ifdef HAVE_EXTENDED_MESSAGING_AND_NAME
extern void queue_enable_queue_send(struct event_queue *q, struct queue_sender_list *send);
extern intptr_t queue_send(struct event_queue *q, long id, intptr_t data);
extern void queue_reply(struct event_queue *q, intptr_t retval);
extern bool queue_in_queue_send(struct event_queue *q);
#endif /* HAVE_EXTENDED_MESSAGING_AND_NAME */
extern bool queue_empty(const struct event_queue* q);
extern void queue_clear(struct event_queue* q);
extern void queue_remove_from_head(struct event_queue *q, long id);
extern int queue_broadcast(long id, intptr_t data);

extern void mutex_init(struct mutex *m);
static inline void spinlock_init(struct mutex *m)
{ mutex_init(m); } /* Same thing for now */
extern void mutex_lock(struct mutex *m);
extern void mutex_unlock(struct mutex *m);
extern void spinlock_lock(struct mutex *m);
extern void spinlock_unlock(struct mutex *m);
extern void tick_start(unsigned int interval_in_ms);

#define IS_SYSEVENT(ev) ((ev & SYS_EVENT) == SYS_EVENT)

#endif