Merge branch 'master' of gitosis@git.osmocom.org:osmocom-bb
authorAndreas Eversberg <jolly@eversberg.eu>
Thu, 29 Apr 2010 18:47:28 +0000 (20:47 +0200)
committerAndreas Eversberg <jolly@eversberg.eu>
Thu, 29 Apr 2010 18:47:28 +0000 (20:47 +0200)
20 files changed:
src/shared/libosmocore/.gitignore
src/shared/libosmocore/include/osmocore/Makefile.am
src/shared/libosmocore/include/osmocore/gsm0808.h [new file with mode: 0644]
src/shared/libosmocore/include/osmocore/gsm_utils.h
src/shared/libosmocore/include/osmocore/protocol/gsm_08_08.h [new file with mode: 0644]
src/shared/libosmocore/src/Makefile.am
src/shared/libosmocore/src/gsm0808.c [new file with mode: 0644]
src/shared/libosmocore/src/select.c
src/target/firmware/include/layer1/mframe_sched.h
src/target/firmware/include/layer1/sync.h
src/target/firmware/layer1/async.c
src/target/firmware/layer1/l23_api.c
src/target/firmware/layer1/mframe_sched.c
src/target/firmware/layer1/prim_fbsb.c
src/target/firmware/layer1/sync.c
src/target/firmware/layer1/tdma_sched.c
src/target_dsp/calypso/dump2coff.py [new file with mode: 0755]
src/target_dsp/calypso/ida/README.txt [new file with mode: 0644]
src/target_dsp/calypso/ida/ndb.h [new file with mode: 0644]
src/target_dsp/calypso/ida/tms320c54.cfg [new file with mode: 0644]

index d61cdc5..06904fa 100644 (file)
@@ -7,6 +7,7 @@ Makefile.in
 *.la
 *.pc
 aclocal.m4
+m4/*.m4
 autom4te.cache
 config.h*
 config.sub
@@ -23,3 +24,7 @@ libtool
 
 .tarball-version
 .version
+
+tests/sms/sms_test
+tests/timer/timer_test
+
index 1c3a33f..56f926b 100644 (file)
@@ -1,7 +1,7 @@
 osmocore_HEADERS = signal.h linuxlist.h timer.h select.h msgb.h \
                   tlv.h bitvec.h comp128.h statistics.h gsm_utils.h utils.h \
                   gsmtap.h write_queue.h rsl.h gsm48.h rxlev_stat.h mncc.h \
-                  gsm48_ie.h logging.h
+                  gsm48_ie.h logging.h gsm0808.h
 
 if ENABLE_TALLOC
 osmocore_HEADERS += talloc.h
diff --git a/src/shared/libosmocore/include/osmocore/gsm0808.h b/src/shared/libosmocore/include/osmocore/gsm0808.h
new file mode 100644 (file)
index 0000000..a40713f
--- /dev/null
@@ -0,0 +1,41 @@
+/* (C) 2009,2010 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2009,2010 by On-Waves
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+#ifndef OSMOCORE_GSM0808_H
+#define OSMOCORE_GSM0808_H
+
+#include "tlv.h"
+
+struct msgb;
+
+struct msgb *gsm0808_create_layer3(struct msgb *msg, uint16_t netcode, uint16_t countrycode, int lac, int ci);
+struct msgb *gsm0808_create_reset(void);
+struct msgb *gsm0808_create_clear_complete(void);
+struct msgb *gsm0808_create_cipher_complete(struct msgb *layer3, uint8_t alg_id);
+struct msgb *gsm0808_create_cipher_reject(uint8_t cause);
+struct msgb *gsm0808_create_classmark_update(const uint8_t *classmark, uint8_t length);
+struct msgb *gsm0808_create_sapi_reject(uint8_t link_id);
+struct msgb *gsm0808_create_assignment_completed(struct gsm_lchan *lchan, uint8_t rr_cause,
+                                                uint8_t chosen_channel, uint8_t encr_alg_id,
+                                                uint8_t speech_mode);
+struct msgb *gsm0808_create_assignment_failure(uint8_t cause, uint8_t *rr_cause);
+
+const struct tlv_definition *gsm0808_att_tlvdef();
+
+#endif
index c87e967..195e865 100644 (file)
 
 #include <stdint.h>
 
+#define ADD_MODULO(sum, delta, modulo) do {    \
+       if ((sum += delta) >= modulo)           \
+               sum -= modulo;                  \
+       } while (0)
+
+#define GSM_MAX_FN     (26*51*2048)
+
 struct gsm_time {
        uint32_t        fn;     /* FN count */
        uint16_t        t1;     /* FN div (26*51) */
diff --git a/src/shared/libosmocore/include/osmocore/protocol/gsm_08_08.h b/src/shared/libosmocore/include/osmocore/protocol/gsm_08_08.h
new file mode 100644 (file)
index 0000000..6b8f935
--- /dev/null
@@ -0,0 +1,303 @@
+/* From GSM08.08 */
+
+#ifndef GSM_0808_H
+#define GSM_0808_H
+
+#include <stdlib.h>
+
+/*
+ * this is from GSM 03.03 CGI but is copied in GSM 08.08
+ * in § 3.2.2.27 for Cell Identifier List
+ */
+enum CELL_IDENT {
+       CELL_IDENT_WHOLE_GLOBAL         = 0,
+       CELL_IDENT_LAC_AND_CI           = 1,
+       CELL_IDENT_CI                   = 2,
+       CELL_IDENT_NO_CELL              = 3,
+       CELL_IDENT_LAI_AND_LAC          = 4,
+       CELL_IDENT_LAC                  = 5,
+       CELL_IDENT_BSS                  = 6,
+       CELL_IDENT_UTRAN_PLMN_LAC_RNC   = 8,
+       CELL_IDENT_UTRAN_RNC            = 9,
+       CELL_IDENT_UTRAN_LAC_RNC        = 10,
+};
+
+
+/* GSM 08.06 § 6.3 */
+enum BSSAP_MSG_TYPE {
+       BSSAP_MSG_BSS_MANAGEMENT    = 0x0,
+       BSSAP_MSG_DTAP              = 0x1,
+};
+
+struct bssmap_header {
+       uint8_t type;
+       uint8_t length;
+} __attribute__((packed));
+
+struct dtap_header {
+       uint8_t type;
+       uint8_t link_id;
+       uint8_t length;
+} __attribute__((packed));
+
+
+enum BSS_MAP_MSG_TYPE {
+       BSS_MAP_MSG_RESERVED_0          = 0,
+
+       /* ASSIGNMENT MESSAGES */
+       BSS_MAP_MSG_ASSIGMENT_RQST      = 1,
+       BSS_MAP_MSG_ASSIGMENT_COMPLETE  = 2,
+       BSS_MAP_MSG_ASSIGMENT_FAILURE   = 3,
+
+       /*  HANDOVER MESSAGES */
+       BSS_MAP_MSG_HANDOVER_RQST               = 16,
+       BSS_MAP_MSG_HANDOVER_REQUIRED           = 17,
+       BSS_MAP_MSG_HANDOVER_RQST_ACKNOWLEDGE= 18,
+       BSS_MAP_MSG_HANDOVER_CMD                = 19,
+       BSS_MAP_MSG_HANDOVER_COMPLETE           = 20,
+       BSS_MAP_MSG_HANDOVER_SUCCEEDED          = 21,
+       BSS_MAP_MSG_HANDOVER_FAILURE            = 22,
+       BSS_MAP_MSG_HANDOVER_PERFORMED          = 23,
+       BSS_MAP_MSG_HANDOVER_CANDIDATE_ENQUIRE  = 24,
+       BSS_MAP_MSG_HANDOVER_CANDIDATE_RESPONSE = 25,
+       BSS_MAP_MSG_HANDOVER_REQUIRED_REJECT    = 26,
+       BSS_MAP_MSG_HANDOVER_DETECT             = 27,
+
+       /* RELEASE MESSAGES */
+       BSS_MAP_MSG_CLEAR_CMD           = 32,
+       BSS_MAP_MSG_CLEAR_COMPLETE              = 33,
+       BSS_MAP_MSG_CLEAR_RQST          = 34,
+       BSS_MAP_MSG_RESERVED_1                  = 35,
+       BSS_MAP_MSG_RESERVED_2                  = 36,
+       BSS_MAP_MSG_SAPI_N_REJECT               = 37,
+       BSS_MAP_MSG_CONFUSION                   = 38,
+
+       /* OTHER CONNECTION RELATED MESSAGES */
+       BSS_MAP_MSG_SUSPEND                     = 40,
+       BSS_MAP_MSG_RESUME                      = 41,
+       BSS_MAP_MSG_CONNECTION_ORIENTED_INFORMATION = 42,
+       BSS_MAP_MSG_PERFORM_LOCATION_RQST       = 43,
+       BSS_MAP_MSG_LSA_INFORMATION             = 44,
+       BSS_MAP_MSG_PERFORM_LOCATION_RESPONSE   = 45,
+       BSS_MAP_MSG_PERFORM_LOCATION_ABORT      = 46,
+       BSS_MAP_MSG_COMMON_ID                   = 47,
+
+       /* GENERAL MESSAGES */
+       BSS_MAP_MSG_RESET                       = 48,
+       BSS_MAP_MSG_RESET_ACKNOWLEDGE           = 49,
+       BSS_MAP_MSG_OVERLOAD                    = 50,
+       BSS_MAP_MSG_RESERVED_3                  = 51,
+       BSS_MAP_MSG_RESET_CIRCUIT               = 52,
+       BSS_MAP_MSG_RESET_CIRCUIT_ACKNOWLEDGE   = 53,
+       BSS_MAP_MSG_MSC_INVOKE_TRACE            = 54,
+       BSS_MAP_MSG_BSS_INVOKE_TRACE            = 55,
+       BSS_MAP_MSG_CONNECTIONLESS_INFORMATION  = 58,
+
+       /* TERRESTRIAL RESOURCE MESSAGES */
+       BSS_MAP_MSG_BLOCK                       = 64,
+       BSS_MAP_MSG_BLOCKING_ACKNOWLEDGE        = 65,
+       BSS_MAP_MSG_UNBLOCK                     = 66,
+       BSS_MAP_MSG_UNBLOCKING_ACKNOWLEDGE      = 67,
+       BSS_MAP_MSG_CIRCUIT_GROUP_BLOCK         = 68,
+       BSS_MAP_MSG_CIRCUIT_GROUP_BLOCKING_ACKNOWLEDGE  = 69,
+       BSS_MAP_MSG_CIRCUIT_GROUP_UNBLOCK       = 70,
+       BSS_MAP_MSG_CIRCUIT_GROUP_UNBLOCKING_ACKNOWLEDGE = 71,
+       BSS_MAP_MSG_UNEQUIPPED_CIRCUIT          = 72,
+       BSS_MAP_MSG_CHANGE_CIRCUIT              = 78,
+       BSS_MAP_MSG_CHANGE_CIRCUIT_ACKNOWLEDGE  = 79,
+
+       /* RADIO RESOURCE MESSAGES */
+       BSS_MAP_MSG_RESOURCE_RQST               = 80,
+       BSS_MAP_MSG_RESOURCE_INDICATION         = 81,
+       BSS_MAP_MSG_PAGING                      = 82,
+       BSS_MAP_MSG_CIPHER_MODE_CMD             = 83,
+       BSS_MAP_MSG_CLASSMARK_UPDATE            = 84,
+       BSS_MAP_MSG_CIPHER_MODE_COMPLETE        = 85,
+       BSS_MAP_MSG_QUEUING_INDICATION          = 86,
+       BSS_MAP_MSG_COMPLETE_LAYER_3            = 87,
+       BSS_MAP_MSG_CLASSMARK_RQST              = 88,
+       BSS_MAP_MSG_CIPHER_MODE_REJECT          = 89,
+       BSS_MAP_MSG_LOAD_INDICATION             = 90,
+
+       /* VGCS/VBS */
+       BSS_MAP_MSG_VGCS_VBS_SETUP              = 4,
+       BSS_MAP_MSG_VGCS_VBS_SETUP_ACK          = 5,
+       BSS_MAP_MSG_VGCS_VBS_SETUP_REFUSE       = 6,
+       BSS_MAP_MSG_VGCS_VBS_ASSIGNMENT_RQST    = 7,
+       BSS_MAP_MSG_VGCS_VBS_ASSIGNMENT_RESULT  = 28,
+       BSS_MAP_MSG_VGCS_VBS_ASSIGNMENT_FAILURE = 29,
+       BSS_MAP_MSG_VGCS_VBS_QUEUING_INDICATION = 30,
+       BSS_MAP_MSG_UPLINK_RQST         = 31,
+       BSS_MAP_MSG_UPLINK_RQST_ACKNOWLEDGE     = 39,
+       BSS_MAP_MSG_UPLINK_RQST_CONFIRMATION    = 73,
+       BSS_MAP_MSG_UPLINK_RELEASE_INDICATION   = 74,
+       BSS_MAP_MSG_UPLINK_REJECT_CMD   = 75,
+       BSS_MAP_MSG_UPLINK_RELEASE_CMD  = 76,
+       BSS_MAP_MSG_UPLINK_SEIZED_CMD   = 77,
+};
+
+enum GSM0808_IE_CODING {
+       GSM0808_IE_CIRCUIT_IDENTITY_CODE        = 1,
+       GSM0808_IE_RESERVED_0                   = 2,
+       GSM0808_IE_RESOURCE_AVAILABLE           = 3,
+       GSM0808_IE_CAUSE                        = 4,
+       GSM0808_IE_CELL_IDENTIFIER              = 5,
+       GSM0808_IE_PRIORITY                     = 6,
+       GSM0808_IE_LAYER_3_HEADER_INFORMATION   = 7,
+       GSM0808_IE_IMSI                         = 8,
+       GSM0808_IE_TMSI                         = 9,
+       GSM0808_IE_ENCRYPTION_INFORMATION       = 10,
+       GSM0808_IE_CHANNEL_TYPE                 = 11,
+       GSM0808_IE_PERIODICITY                  = 12,
+       GSM0808_IE_EXTENDED_RESOURCE_INDICATOR  = 13,
+       GSM0808_IE_NUMBER_OF_MSS                = 14,
+       GSM0808_IE_RESERVED_1                   = 15,
+       GSM0808_IE_RESERVED_2                   = 16,
+       GSM0808_IE_RESERVED_3                   = 17,
+       GSM0808_IE_CLASSMARK_INFORMATION_T2     = 18,
+       GSM0808_IE_CLASSMARK_INFORMATION_T3     = 19,
+       GSM0808_IE_INTERFERENCE_BAND_TO_USE     = 20,
+       GSM0808_IE_RR_CAUSE                     = 21,
+       GSM0808_IE_RESERVED_4                   = 22,
+       GSM0808_IE_LAYER_3_INFORMATION          = 23,
+       GSM0808_IE_DLCI                         = 24,
+       GSM0808_IE_DOWNLINK_DTX_FLAG            = 25,
+       GSM0808_IE_CELL_IDENTIFIER_LIST         = 26,
+       GSM0808_IE_RESPONSE_RQST                = 27,
+       GSM0808_IE_RESOURCE_INDICATION_METHOD   = 28,
+       GSM0808_IE_CLASSMARK_INFORMATION_TYPE_1 = 29,
+       GSM0808_IE_CIRCUIT_IDENTITY_CODE_LIST   = 30,
+       GSM0808_IE_DIAGNOSTIC                   = 31,
+       GSM0808_IE_LAYER_3_MESSAGE_CONTENTS     = 32,
+       GSM0808_IE_CHOSEN_CHANNEL               = 33,
+       GSM0808_IE_TOTAL_RESOURCE_ACCESSIBLE    = 34,
+       GSM0808_IE_CIPHER_RESPONSE_MODE         = 35,
+       GSM0808_IE_CHANNEL_NEEDED               = 36,
+       GSM0808_IE_TRACE_TYPE                   = 37,
+       GSM0808_IE_TRIGGERID                    = 38,
+       GSM0808_IE_TRACE_REFERENCE              = 39,
+       GSM0808_IE_TRANSACTIONID                = 40,
+       GSM0808_IE_MOBILE_IDENTITY              = 41,
+       GSM0808_IE_OMCID                        = 42,
+       GSM0808_IE_FORWARD_INDICATOR            = 43,
+       GSM0808_IE_CHOSEN_ENCR_ALG              = 44,
+       GSM0808_IE_CIRCUIT_POOL                 = 45,
+       GSM0808_IE_CIRCUIT_POOL_LIST            = 46,
+       GSM0808_IE_TIME_INDICATION              = 47,
+       GSM0808_IE_RESOURCE_SITUATION           = 48,
+       GSM0808_IE_CURRENT_CHANNEL_TYPE_1       = 49,
+       GSM0808_IE_QUEUEING_INDICATOR           = 50,
+       GSM0808_IE_SPEECH_VERSION               = 64,
+       GSM0808_IE_ASSIGNMENT_REQUIREMENT       = 51,
+       GSM0808_IE_TALKER_FLAG                  = 53,
+       GSM0808_IE_CONNECTION_RELEASE_RQSTED    = 54,
+       GSM0808_IE_GROUP_CALL_REFERENCE         = 55,
+       GSM0808_IE_EMLPP_PRIORITY               = 56,
+       GSM0808_IE_CONFIG_EVO_INDI              = 57,
+       GSM0808_IE_OLD_BSS_TO_NEW_BSS_INFORMATION       = 58,
+       GSM0808_IE_LSA_IDENTIFIER               = 59,
+       GSM0808_IE_LSA_IDENTIFIER_LIST          = 60,
+       GSM0808_IE_LSA_INFORMATION              = 61,
+       GSM0808_IE_LCS_QOS                      = 62,
+       GSM0808_IE_LSA_ACCESS_CTRL_SUPPR        = 63,
+       GSM0808_IE_LCS_PRIORITY                 = 67,
+       GSM0808_IE_LOCATION_TYPE                = 68,
+       GSM0808_IE_LOCATION_ESTIMATE            = 69,
+       GSM0808_IE_POSITIONING_DATA             = 70,
+       GSM0808_IE_LCS_CAUSE                    = 71,
+       GSM0808_IE_LCS_CLIENT_TYPE              = 72,
+       GSM0808_IE_APDU                         = 73,
+       GSM0808_IE_NETWORK_ELEMENT_IDENTITY     = 74,
+       GSM0808_IE_GPS_ASSISTANCE_DATA          = 75,
+       GSM0808_IE_DECIPHERING_KEYS             = 76,
+       GSM0808_IE_RETURN_ERROR_RQST            = 77,
+       GSM0808_IE_RETURN_ERROR_CAUSE           = 78,
+       GSM0808_IE_SEGMENTATION                 = 79,
+       GSM0808_IE_SERVICE_HANDOVER             = 80,
+       GSM0808_IE_SOURCE_RNC_TO_TARGET_RNC_TRANSPARENT_UMTS    = 81,
+       GSM0808_IE_SOURCE_RNC_TO_TARGET_RNC_TRANSPARENT_CDMA2000= 82,
+       GSM0808_IE_RESERVED_5                   = 65,
+       GSM0808_IE_RESERVED_6                   = 66,
+};
+
+enum gsm0808_cause {
+       GSM0808_CAUSE_RADIO_INTERFACE_MESSAGE_FAILURE                   = 0,
+       GSM0808_CAUSE_RADIO_INTERFACE_FAILURE                           = 1,
+       GSM0808_CAUSE_UPLINK_QUALITY                                    = 2,
+       GSM0808_CAUSE_UPLINK_STRENGTH                                   = 3,
+       GSM0808_CAUSE_DOWNLINK_QUALITY                                  = 4,
+       GSM0808_CAUSE_DOWNLINK_STRENGTH                                 = 5,
+       GSM0808_CAUSE_DISTANCE                                          = 6,
+       GSM0808_CAUSE_O_AND_M_INTERVENTION                              = 7,
+       GSM0808_CAUSE_RESPONSE_TO_MSC_INVOCATION                        = 8,
+       GSM0808_CAUSE_CALL_CONTROL                                      = 9,
+       GSM0808_CAUSE_RADIO_INTERFACE_FAILURE_REVERSION                 = 10,
+       GSM0808_CAUSE_HANDOVER_SUCCESSFUL                               = 11,
+       GSM0808_CAUSE_BETTER_CELL                                       = 12,
+       GSM0808_CAUSE_DIRECTED_RETRY                                    = 13,
+       GSM0808_CAUSE_JOINED_GROUP_CALL_CHANNEL                         = 14,
+       GSM0808_CAUSE_TRAFFIC                                           = 15,
+       GSM0808_CAUSE_EQUIPMENT_FAILURE                                 = 32,
+       GSM0808_CAUSE_NO_RADIO_RESOURCE_AVAILABLE                       = 33,
+       GSM0808_CAUSE_RQSTED_TERRESTRIAL_RESOURCE_UNAVAILABLE   = 34,
+       GSM0808_CAUSE_CCCH_OVERLOAD                                     = 35,
+       GSM0808_CAUSE_PROCESSOR_OVERLOAD                                = 36,
+       GSM0808_CAUSE_BSS_NOT_EQUIPPED                                  = 37,
+       GSM0808_CAUSE_MS_NOT_EQUIPPED                                   = 38,
+       GSM0808_CAUSE_INVALID_CELL                                      = 39,
+       GSM0808_CAUSE_TRAFFIC_LOAD                                      = 40,
+       GSM0808_CAUSE_PREEMPTION                                        = 41,
+       GSM0808_CAUSE_RQSTED_TRANSCODING_RATE_ADAPTION_UNAVAILABLE      = 48,
+       GSM0808_CAUSE_CIRCUIT_POOL_MISMATCH                             = 49,
+       GSM0808_CAUSE_SWITCH_CIRCUIT_POOL                               = 50,
+       GSM0808_CAUSE_RQSTED_SPEECH_VERSION_UNAVAILABLE         = 51,
+       GSM0808_CAUSE_LSA_NOT_ALLOWED                                   = 52,
+       GSM0808_CAUSE_CIPHERING_ALGORITHM_NOT_SUPPORTED                 = 64,
+       GSM0808_CAUSE_TERRESTRIAL_CIRCUIT_ALREADY_ALLOCATED             = 80,
+       GSM0808_CAUSE_INVALID_MESSAGE_CONTENTS                          = 81,
+       GSM0808_CAUSE_INFORMATION_ELEMENT_OR_FIELD_MISSING              = 82,
+       GSM0808_CAUSE_INCORRECT_VALUE                                   = 83,
+       GSM0808_CAUSE_UNKNOWN_MESSAGE_TYPE                              = 84,
+       GSM0808_CAUSE_UNKNOWN_INFORMATION_ELEMENT                       = 85,
+       GSM0808_CAUSE_PROTOCOL_ERROR_BETWEEN_BSS_AND_MSC                = 96,
+};
+
+/* GSM 08.08 3.2.2.11 Channel Type */
+enum gsm0808_chan_indicator {
+       GSM0808_CHAN_SPEECH = 1,
+       GSM0808_CHAN_DATA   = 2,
+       GSM0808_CHAN_SIGN   = 3,
+};
+
+enum gsm0808_chan_rate_type_data {
+       GSM0808_DATA_FULL_BM    = 0x8,
+       GSM0808_DATA_HALF_LM    = 0x9,
+       GSM0808_DATA_FULL_RPREF = 0xa,
+       GSM0808_DATA_HALF_PREF  = 0xb,
+       GSM0808_DATA_FULL_PREF_NO_CHANGE        = 0x1a,
+       GSM0808_DATA_HALF_PREF_NO_CHANGE        = 0x1b,
+       GSM0808_DATA_MULTI_MASK = 0x20,
+       GSM0808_DATA_MULTI_MASK_NO_CHANGE       = 0x30,
+};
+
+enum gsm0808_chan_rate_type_speech {
+       GSM0808_SPEECH_FULL_BM  = 0x8,
+       GSM0808_SPEECH_HALF_LM  = 0x9,
+       GSM0808_SPEECH_FULL_PREF= 0xa,
+       GSM0808_SPEECH_HALF_PREF= 0xb,
+       GSM0808_SPEECH_FULL_PREF_NO_CHANGE      = 0x1a,
+       GSM0808_SPEECH_HALF_PREF_NO_CHANGE      = 0x1b,
+       GSM0808_SPEECH_PERM     = 0xf,
+       GSM0808_SPEECH_PERM_NO_CHANGE = 0x1f,
+};
+
+enum gsm0808_permitted_speech {
+       GSM0808_PERM_FR1        = 0x01,
+       GSM0808_PERM_FR2        = 0x11,
+       GSM0808_PERM_FR3        = 0x21,
+       GSM0808_PERM_HR1        = GSM0808_PERM_FR1 | 0x4,
+       GSM0808_PERM_HR2        = GSM0808_PERM_FR2 | 0x4,
+       GSM0808_PERM_HR3        = GSM0808_PERM_FR3 | 0x4,
+};
+
+#endif
index 1697807..20e99db 100644 (file)
@@ -10,7 +10,7 @@ lib_LTLIBRARIES = libosmocore.la
 libosmocore_la_SOURCES = timer.c select.c signal.c msgb.c rxlev_stat.c \
                         tlv_parser.c bitvec.c comp128.c gsm_utils.c statistics.c \
                         write_queue.c utils.c rsl.c gsm48.c gsm48_ie.c \
-                        logging.c
+                        logging.c gsm0808.c
 
 if ENABLE_TALLOC
 libosmocore_la_SOURCES += talloc.c
diff --git a/src/shared/libosmocore/src/gsm0808.c b/src/shared/libosmocore/src/gsm0808.c
new file mode 100644 (file)
index 0000000..7a7eb3a
--- /dev/null
@@ -0,0 +1,295 @@
+/* (C) 2009,2010 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2009,2010 by On-Waves
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <osmocore/gsm0808.h>
+#include <osmocore/protocol/gsm_08_08.h>
+#include <osmocore/gsm48.h>
+
+#include <arpa/inet.h>
+
+#define BSSMAP_MSG_SIZE 512
+#define BSSMAP_MSG_HEADROOM 128
+
+struct msgb *gsm0808_create_layer3(struct msgb *msg_l3, uint16_t nc, uint16_t cc, int lac, int _ci)
+{
+       uint8_t *data;
+       uint16_t *ci;
+       struct msgb* msg;
+       struct gsm48_loc_area_id *lai;
+
+       msg  = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,
+                                  "bssmap cmpl l3");
+       if (!msg)
+               return NULL;
+
+       /* create the bssmap header */
+       msg->l3h = msgb_put(msg, 2);
+       msg->l3h[0] = 0x0;
+
+       /* create layer 3 header */
+       data = msgb_put(msg, 1);
+       data[0] = BSS_MAP_MSG_COMPLETE_LAYER_3;
+
+       /* create the cell header */
+       data = msgb_put(msg, 3);
+       data[0] = GSM0808_IE_CELL_IDENTIFIER;
+       data[1] = 1 + sizeof(*lai) + 2;
+       data[2] = CELL_IDENT_WHOLE_GLOBAL;
+
+       lai = (struct gsm48_loc_area_id *) msgb_put(msg, sizeof(*lai));
+       gsm48_generate_lai(lai, cc, nc, lac);
+
+       ci = (uint16_t *) msgb_put(msg, 2);
+       *ci = htons(_ci);
+
+       /* copy the layer3 data */
+       data = msgb_put(msg, msgb_l3len(msg_l3) + 2);
+       data[0] = GSM0808_IE_LAYER_3_INFORMATION;
+       data[1] = msgb_l3len(msg_l3);
+       memcpy(&data[2], msg_l3->l3h, data[1]);
+
+       /* update the size */
+       msg->l3h[1] = msgb_l3len(msg) - 2;
+
+       return msg;
+}
+
+struct msgb *gsm0808_create_reset(void)
+{
+       struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,
+                                              "bssmap: reset");
+       if (!msg)
+               return NULL;
+
+       msg->l3h = msgb_put(msg, 6);
+       msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT;
+       msg->l3h[1] = 0x04;
+       msg->l3h[2] = 0x30;
+       msg->l3h[3] = 0x04;
+       msg->l3h[4] = 0x01;
+       msg->l3h[5] = 0x20;
+       return msg;
+}
+
+struct msgb *gsm0808_create_clear_complete(void)
+{
+       struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,
+                                              "bssmap: clear complete");
+       if (!msg)
+               return NULL;
+
+       msg->l3h = msgb_put(msg, 3);
+       msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT;
+       msg->l3h[1] = 1;
+       msg->l3h[2] = BSS_MAP_MSG_CLEAR_COMPLETE;
+
+       return msg;
+}
+
+struct msgb *gsm0808_create_cipher_complete(struct msgb *layer3, uint8_t alg_id)
+{
+       struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,
+                                              "cipher-complete");
+       if (!msg)
+               return NULL;
+
+        /* send response with BSS override for A5/1... cheating */
+       msg->l3h = msgb_put(msg, 3);
+       msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT;
+       msg->l3h[1] = 0xff;
+       msg->l3h[2] = BSS_MAP_MSG_CIPHER_MODE_COMPLETE;
+
+       /* include layer3 in case we have at least two octets */
+       if (layer3 && msgb_l3len(layer3) > 2) {
+               msg->l4h = msgb_put(msg, msgb_l3len(layer3) + 2);
+               msg->l4h[0] = GSM0808_IE_LAYER_3_MESSAGE_CONTENTS;
+               msg->l4h[1] = msgb_l3len(layer3);
+               memcpy(&msg->l4h[2], layer3->l3h, msgb_l3len(layer3));
+       }
+
+       /* and the optional BSS message */
+       msg->l4h = msgb_put(msg, 2);
+       msg->l4h[0] = GSM0808_IE_CHOSEN_ENCR_ALG;
+       msg->l4h[1] = alg_id;
+
+       /* update the size */
+       msg->l3h[1] = msgb_l3len(msg) - 2;
+       return msg;
+}
+
+struct msgb *gsm0808_create_cipher_reject(uint8_t cause)
+{
+       struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,
+                                              "bssmap: clear complete");
+       if (!msg)
+               return NULL;
+
+       msg->l3h = msgb_put(msg, 3);
+       msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT;
+       msg->l3h[1] = 2;
+       msg->l3h[2] = BSS_MAP_MSG_CIPHER_MODE_REJECT;
+       msg->l3h[3] = cause;
+
+       return msg;
+}
+
+struct msgb *gsm0808_create_classmark_update(const uint8_t *classmark_data, uint8_t length)
+{
+       struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,
+                                              "classmark-update");
+       if (!msg)
+               return NULL;
+
+       msg->l3h = msgb_put(msg, 3);
+       msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT;
+       msg->l3h[1] = 0xff;
+       msg->l3h[2] = BSS_MAP_MSG_CLASSMARK_UPDATE;
+
+       msg->l4h = msgb_put(msg, length);
+       memcpy(msg->l4h, classmark_data, length);
+
+       /* update the size */
+       msg->l3h[1] = msgb_l3len(msg) - 2;
+       return msg;
+}
+
+struct msgb *gsm0808_create_sapi_reject(uint8_t link_id)
+{
+       struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,
+                                              "bssmap: sapi 'n' reject");
+       if (!msg)
+               return NULL;
+
+       msg->l3h = msgb_put(msg, 5);
+       msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT;
+       msg->l3h[1] = 3;
+       msg->l3h[2] = BSS_MAP_MSG_SAPI_N_REJECT;
+       msg->l3h[3] = link_id;
+       msg->l3h[4] = GSM0808_CAUSE_BSS_NOT_EQUIPPED;
+
+       return msg;
+}
+
+struct msgb *gsm0808_create_assignment_completed(struct gsm_lchan *lchan, uint8_t rr_cause,
+                                                uint8_t chosen_channel, uint8_t encr_alg_id,
+                                                uint8_t speech_mode)
+{
+       uint8_t *data;
+
+       struct msgb *msg = msgb_alloc(35, "bssmap: ass compl");
+       if (!msg)
+               return NULL;
+
+       msg->l3h = msgb_put(msg, 3);
+       msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT;
+       msg->l3h[1] = 0xff;
+       msg->l3h[2] = BSS_MAP_MSG_ASSIGMENT_COMPLETE;
+
+       /* write 3.2.2.22 */
+       data = msgb_put(msg, 2);
+       data[0] = GSM0808_IE_RR_CAUSE;
+       data[1] = rr_cause;
+
+       /* write cirtcuit identity  code 3.2.2.2 */
+       /* write cell identifier 3.2.2.17 */
+       /* write chosen channel 3.2.2.33 when BTS picked it */
+       data = msgb_put(msg, 2);
+       data[0] = GSM0808_IE_CHOSEN_CHANNEL;
+       data[1] = chosen_channel;
+
+       /* write chosen encryption algorithm 3.2.2.44 */
+       data = msgb_put(msg, 2);
+       data[0] = GSM0808_IE_CHOSEN_ENCR_ALG;
+       data[1] = encr_alg_id;
+
+       /* write circuit pool 3.2.2.45 */
+       /* write speech version chosen: 3.2.2.51 when BTS picked it */
+       if (speech_mode != 0) {
+               data = msgb_put(msg, 2);
+               data[0] = GSM0808_IE_SPEECH_VERSION;
+               data[1] = speech_mode;
+       }
+
+       /* write LSA identifier 3.2.2.15 */
+
+
+       /* update the size */
+       msg->l3h[1] = msgb_l3len(msg) - 2;
+       return msg;
+}
+
+struct msgb *gsm0808_create_assignment_failure(uint8_t cause, uint8_t *rr_cause)
+{
+       uint8_t *data;
+       struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,
+                                              "bssmap: ass fail");
+       if (!msg)
+               return NULL;
+
+       msg->l3h = msgb_put(msg, 6);
+       msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT;
+       msg->l3h[1] = 0xff;
+       msg->l3h[2] = BSS_MAP_MSG_ASSIGMENT_FAILURE;
+       msg->l3h[3] = GSM0808_IE_CAUSE;
+       msg->l3h[4] = 1;
+       msg->l3h[5] = cause;
+
+       /* RR cause 3.2.2.22 */
+       if (rr_cause) {
+               data = msgb_put(msg, 2);
+               data[0] = GSM0808_IE_RR_CAUSE;
+               data[1] = *rr_cause;
+       }
+
+       /* Circuit pool 3.22.45 */
+       /* Circuit pool list 3.2.2.46 */
+
+       /* update the size */
+       msg->l3h[1] = msgb_l3len(msg) - 2;
+       return msg;
+}
+
+static const struct tlv_definition bss_att_tlvdef = {
+       .def = {
+               [GSM0808_IE_IMSI]                   = { TLV_TYPE_TLV },
+               [GSM0808_IE_TMSI]                   = { TLV_TYPE_TLV },
+               [GSM0808_IE_CELL_IDENTIFIER_LIST]   = { TLV_TYPE_TLV },
+               [GSM0808_IE_CHANNEL_NEEDED]         = { TLV_TYPE_TV },
+               [GSM0808_IE_EMLPP_PRIORITY]         = { TLV_TYPE_TV },
+               [GSM0808_IE_CHANNEL_TYPE]           = { TLV_TYPE_TLV },
+               [GSM0808_IE_PRIORITY]               = { TLV_TYPE_TLV },
+               [GSM0808_IE_CIRCUIT_IDENTITY_CODE]  = { TLV_TYPE_TV },
+               [GSM0808_IE_DOWNLINK_DTX_FLAG]      = { TLV_TYPE_TV },
+               [GSM0808_IE_INTERFERENCE_BAND_TO_USE] = { TLV_TYPE_TV },
+               [GSM0808_IE_CLASSMARK_INFORMATION_T2] = { TLV_TYPE_TLV },
+               [GSM0808_IE_GROUP_CALL_REFERENCE]   = { TLV_TYPE_TLV },
+               [GSM0808_IE_TALKER_FLAG]            = { TLV_TYPE_T },
+               [GSM0808_IE_CONFIG_EVO_INDI]        = { TLV_TYPE_TV },
+               [GSM0808_IE_LSA_ACCESS_CTRL_SUPPR]  = { TLV_TYPE_TV },
+               [GSM0808_IE_SERVICE_HANDOVER]       = { TLV_TYPE_TV},
+               [GSM0808_IE_ENCRYPTION_INFORMATION] = { TLV_TYPE_TLV },
+               [GSM0808_IE_CIPHER_RESPONSE_MODE]   = { TLV_TYPE_TV },
+       },
+};
+
+const struct tlv_definition *gsm0808_att_tlvdef()
+{
+       return &bss_att_tlvdef;
+}
index 9517778..2f6afa7 100644 (file)
@@ -121,7 +121,8 @@ restart:
                /* ugly, ugly hack. If more than one filedescriptors were
                 * unregistered, they might have been consecutive and
                 * llist_for_each_entry_safe() is no longer safe */
-               if (unregistered_count > 1)
+               /* this seems to happen with the last element of the list as well */
+               if (unregistered_count >= 1)
                        goto restart;
        }
        return work;
index 87f31a9..5e71dac 100644 (file)
@@ -31,9 +31,28 @@ enum mf_sched_item_flag {
        MF_F_SACCH      = (1 << 0),
 };
 
+/* The scheduler itself */
+struct mframe_scheduler {
+       uint32_t tasks;
+       uint32_t tasks_tgt;
+       uint32_t safe_fn;
+};
+
 uint8_t mframe_task2chan_nr(enum mframe_task mft, uint8_t ts);
 
+/* Enable a specific task */
+void mframe_enable(enum mframe_task task_id);
+
+/* Disable a specific task */
+void mframe_disable(enum mframe_task task_id);
+
+/* Replace the current active set by the new one */
+void mframe_set(uint32_t tasks);
+
 /* Schedule mframe_sched_items according to current MF TASK list */
-void mframe_schedule(uint32_t task_bitmask);
+void mframe_schedule(void);
+
+/* reset the scheduler, disabling all tasks */
+void mframe_reset(void);
 
 #endif /* _MFRAME_SCHED_H */
index 9e19484..d053c93 100644 (file)
@@ -4,6 +4,7 @@
 #include <osmocore/linuxlist.h>
 #include <osmocore/gsm_utils.h>
 #include <layer1/tdma_sched.h>
+#include <layer1/mframe_sched.h>
 #include <l1a_l23_interface.h>
 
 /* structure representing L1 sync information about a cell */
@@ -42,15 +43,15 @@ struct l1s_state {
        /* TDMA scheduler */
        struct tdma_scheduler tdma_sched;
 
+       /* Multiframe scheduler */
+       struct mframe_scheduler mframe_sched;
+
        /* The current TPU offset register */
        uint32_t        tpu_offset;
 
        /* Transmit queues of pending packets for main DCCH and ACCH */
        struct llist_head tx_queue[_NUM_L1S_CHAN];
 
-       /* bit-mask of multi-frame tasks that are currently active */
-       uint32_t        mf_tasks;
-
        /* Structures below are for L1-task specific parameters, used
         * to communicate between l1-sync and l1-async (l23_api) */
        struct {
index 913e183..3db07e1 100644 (file)
@@ -46,15 +46,22 @@ void l1a_txq_msgb_enq(struct llist_head *queue, struct msgb *msg)
 /* Enable a repeating multiframe task */
 void l1a_mftask_enable(enum mframe_task task)
 {
-       /* we don't need locking here as L1S only reads mf_tasks */
-       l1s.mf_tasks |= (1 << task);
+       /* we don't need locking here as L1S only reads mframe.tasks */
+       mframe_enable(task);
 }
 
 /* Disable a repeating multiframe task */
 void l1a_mftask_disable(enum mframe_task task)
 {
-       /* we don't need locking here as L1S only reads mf_tasks */
-       l1s.mf_tasks &= ~(1 << task);
+       /* we don't need locking here as L1S only reads mframe.tasks */
+       mframe_disable(task);
+}
+
+/* Set the mask for repeating multiframe tasks */
+void l1a_mftask_set(uint32_t tasks)
+{
+       /* we don't need locking here as L1S only reads mframe.tasks */
+       mframe_set(tasks);
 }
 
 /* Initialize asynchronous part of Layer1 */
index e54d72b..fec6183 100644 (file)
@@ -204,7 +204,7 @@ static void l1a_l23_rx_cb(uint8_t dlci, struct msgb *msg)
                }
                /* FIXME: set TSC of ded chan according to est_req.h0.tsc */
                /* figure out which MF tasks to enable */
-               l1s.mf_tasks = (1 << chan_nr2mf_task(ul->chan_nr));
+               l1a_mftask_set(1 << chan_nr2mf_task(ul->chan_nr));
                break;
        case L1CTL_RACH_REQ:
                rach_req = (struct l1ctl_rach_req *) ul->payload;
index 92e95ed..e51d758 100644 (file)
@@ -301,20 +301,70 @@ static void mframe_schedule_set(enum mframe_task task_id)
                unsigned int trigger = si->frame_nr % si->modulo;
                unsigned int current = (l1s.current_time.fn + SCHEDULE_AHEAD) % si->modulo;
                if (current == trigger) {
+                       uint32_t fn;
+                       int rv;
+
+                       /* Schedule the set */
                        /* FIXME: what to do with SACCH Flag etc? */
-                       tdma_schedule_set(SCHEDULE_AHEAD-SCHEDULE_LATENCY,
+                       rv = tdma_schedule_set(SCHEDULE_AHEAD-SCHEDULE_LATENCY,
                                          si->sched_set, task_id | (si->flags<<8));
+
+                       /* Compute the next safe time to queue a DSP command */
+                       fn = l1s.current_time.fn;
+                       ADD_MODULO(fn, rv - 2, GSM_MAX_FN); /* -2 = worst case last dsp command */
+                       if ((fn > l1s.mframe_sched.safe_fn) ||
+                           (l1s.mframe_sched.safe_fn >= GSM_MAX_FN))
+                               l1s.mframe_sched.safe_fn = fn;
                }
        }
 }
 
+/* Enable a specific task */
+void mframe_enable(enum mframe_task task_id)
+{
+       l1s.mframe_sched.tasks_tgt |= (1 << task_id);
+}
+
+/* Disable a specific task */
+void mframe_disable(enum mframe_task task_id)
+{
+       l1s.mframe_sched.tasks_tgt &= ~(1 << task_id);
+}
+
+/* Replace the current active set by the new one */
+void mframe_set(uint32_t tasks)
+{
+       l1s.mframe_sched.tasks_tgt = tasks;
+}
+
 /* Schedule mframe_sched_items according to current MF TASK list */
-void mframe_schedule(uint32_t tasks_enabled)
+void mframe_schedule(void)
 {
        unsigned int i;
+       int fn_diff;
+
+       /* Try to enable/disable task to meet target bitmap */
+       fn_diff = l1s.mframe_sched.safe_fn - l1s.current_time.fn;
+       if ((fn_diff <= 0) || (fn_diff >= (GSM_MAX_FN>>1)) ||
+           (l1s.mframe_sched.safe_fn >= GSM_MAX_FN))
+               /* If nothing is in the way, enable new tasks */
+               l1s.mframe_sched.tasks = l1s.mframe_sched.tasks_tgt;
+       else
+               /* Else, Disable only */
+               l1s.mframe_sched.tasks &= l1s.mframe_sched.tasks_tgt;
 
+       /* Schedule any active pending set */
        for (i = 0; i < 32; i++) {
-               if (tasks_enabled & (1 << i))
+               if (l1s.mframe_sched.tasks & (1 << i))
                        mframe_schedule_set(i);
        }
 }
+
+/* reset the scheduler, disabling all tasks */
+void mframe_reset(void)
+{
+       l1s.mframe_sched.tasks = 0;
+       l1s.mframe_sched.tasks_tgt = 0;
+       l1s.mframe_sched.safe_fn = -1UL;        /* Force safe */
+}
+
index 98a8848..3cd14c4 100644 (file)
@@ -416,8 +416,8 @@ static int l1s_sbdet_resp(__unused uint8_t p1, uint8_t attempt,
        if (l1s.sb.count > 10 && sb_time.t3 == 41) {
                l1s_reset_hw();
                /* enable the MF Task for BCCH reading */
-               l1s.mf_tasks |= (1 << MF_TASK_BCCH_NORM);
-               l1s.mf_tasks |= (1 << MF_TASK_CCCH_COMB);
+               mframe_enable(MF_TASK_BCCH_NORM);
+               mframe_enable(MF_TASK_CCCH_COMB);
        } else {
                /* We have just seen a SCH burst, we know the next one
                 * is not in less than 7 TDMA frames from now */
index 9bdaba5..f5629cf 100644 (file)
@@ -65,13 +65,6 @@ void l1s_set_handler(l1s_cb_t cb)
        l1s_cb = cb;
 }
 
-#define ADD_MODULO(sum, delta, modulo) do {    \
-       if ((sum += delta) >= modulo)           \
-               sum -= modulo;                  \
-       } while (0)
-
-#define GSM_MAX_FN     (26*51*2048)
-
 void l1s_time_inc(struct gsm_time *time, uint32_t delta_fn)
 {
        ADD_MODULO(time->fn, delta_fn, GSM_MAX_FN);
@@ -94,7 +87,7 @@ void l1s_time_inc(struct gsm_time *time, uint32_t delta_fn)
 
 void l1s_time_dump(const struct gsm_time *time)
 {
-       printf("fn=%u(%u/%2u/%2u)", time->fn, time->t1, time->t2, time->t3);
+       printf("fn=%lu(%u/%2u/%2u)", time->fn, time->t1, time->t2, time->t3);
 }
 
 /* clip a signed 16bit value at a certain limit */
@@ -264,7 +257,7 @@ static void l1_sync(void)
        //dsp_end_scenario();
 
        /* schedule new / upcoming TDMA items */
-       mframe_schedule(l1s.mf_tasks);
+       mframe_schedule();
        /* schedule new / upcoming one-shot events */
        sched_gsmtime_execute(l1s.current_time.fn);
 
@@ -342,7 +335,7 @@ void l1s_reset(void)
        l1s.sb.count = 0;
 
        /* reset scheduler and hardware */
-       l1s.mf_tasks = 0;
+       mframe_reset();
        tdma_sched_reset();
        l1s_dsp_abort();
 }
index 9469369..8289210 100644 (file)
@@ -78,9 +78,9 @@ int tdma_schedule_set(uint8_t frame_offset, const struct tdma_sched_item *item_s
 {
        struct tdma_scheduler *sched = &l1s.tdma_sched;
        uint8_t bucket_nr = wrap_bucket(frame_offset);
-       int i;
+       int i, j;
 
-       for (i = 0; 1; i++) {
+       for (i = 0, j = 0; 1; i++) {
                const struct tdma_sched_item *sched_item = &item_set[i];
                struct tdma_sched_bucket *bucket = &sched->bucket[bucket_nr];
 
@@ -92,6 +92,7 @@ int tdma_schedule_set(uint8_t frame_offset, const struct tdma_sched_item *item_s
                if (sched_item->cb == NULL) {
                        /* advance to next bucket (== TDMA frame) */
                        bucket_nr = wrap_bucket(++frame_offset);
+                       j++;
                        continue;
                }
                /* check for bucket overflow */
@@ -105,7 +106,7 @@ int tdma_schedule_set(uint8_t frame_offset, const struct tdma_sched_item *item_s
                bucket->num_items++;
        }
 
-       return i;
+       return j;
 }
 
 /* Advance TDMA scheduler to the next bucket */
diff --git a/src/target_dsp/calypso/dump2coff.py b/src/target_dsp/calypso/dump2coff.py
new file mode 100755 (executable)
index 0000000..67a49e8
--- /dev/null
@@ -0,0 +1,261 @@
+#!/usr/bin/env python
+
+from collections import namedtuple
+import re
+import sys
+import struct
+
+DATA = 0
+DATA = 1
+
+
+class Section(object):
+
+       DATA            = 0
+       CODE            = 1
+
+       STYP_NOLOAD     = 0x0002
+       STYP_TEXT       = 0x0020
+       STYP_DATA       = 0x0040
+       STYP_BSS        = 0x0080
+
+       def __init__(self, name, type, start, size, data=None):
+               self.name  = name
+               self.type  = type
+               self.start = start
+               self.size  = size
+               self.data  = data
+
+       @property
+       def flags(self):
+               if self.type == Section.DATA:
+                       return Section.STYP_DATA if self.data else Section.STYP_BSS
+               else:
+                       return Section.STYP_TEXT if self.data else Section.STYP_NOLOAD
+
+
+class CalypsoCOFF(object):
+
+       F_RELFLG        = 0x0001 # Relocation information stripped from the file
+       F_EXEC          = 0x0002 # File is executable (i.e., no unresolved external references)
+       F_LNNO          = 0x0004 # Line numbers stripped from the file
+       F_LSYMS         = 0x0010 # Local symbols stripped from the file
+       F_LITTLE        = 0x0100 # Little endian
+
+       def __init__(self, data_seg_base=0x80000000):
+               self.sections = {}
+               self.data_seg_base = data_seg_base
+               self.ver_magic = 0x00c1
+               self.tgt_magic = 0x0098
+               self.flags = \
+                       CalypsoCOFF.F_RELFLG    |       \
+                       CalypsoCOFF.F_EXEC              |       \
+                       CalypsoCOFF.F_LNNO              |       \
+                       CalypsoCOFF.F_LSYMS             |       \
+                       CalypsoCOFF.F_LITTLE
+
+       def _data_pack(self, d):
+               return ''.join(struct.pack('<H', x) for x in d)
+
+       def save(self, filename):
+               # Formats
+               HDR_FILE = '<HHlllHHH'
+               HDR_SECTIONS = '<8sLLllllHHHcc'
+
+               # Optional header
+               oh = ''
+
+               # File header
+               fh = struct.pack(HDR_FILE,
+                       self.ver_magic,         # unsigned short  f_ver_magic; /* version magic number */
+                       len(self.sections),     # unsigned short  f_nscns;     /* number of section */
+                       0,                                      # long            f_timdat;    /* time and date stamp */
+                       0,                                      # long            f_symptr;    /* file ptr to symbol table */
+                       0,                                      # long            f_nsyms;     /* number entries in the sym table */
+                       len(oh),                        # unsigned short  f_opthdr;    /* size of optional header */
+                       self.flags,                     # unsigned short  f_flags;     /* flags */
+                       self.tgt_magic,         # unsigned short  f_tgt_magic; /* target magic number */
+               )
+
+               # File header size  + #sections * sizeof(section header)
+               dptr = struct.calcsize(HDR_FILE) + len(oh) + len(self.sections) * struct.calcsize(HDR_SECTIONS)
+
+               # Section headers
+               sh = []
+               sd = []
+
+               sk = lambda x: self.data_seg_base + x.start if x.type==Section.DATA else x.start
+
+               for s in sorted(self.sections.values(), key=sk):
+                       # Values
+                       if s.type == Section.DATA:
+                               mp = 0x80
+                               sa = s.start
+                       else:
+                               mp = 0
+                               sa = s.start
+                       sptr = dptr if s.data else 0
+
+                       # Header
+                       sh.append(struct.pack(HDR_SECTIONS,
+                               s.name, # char[8]        s_name;   /* 8-character null padded section name */
+                               sa,             # long int       s_paddr;  /* Physical address of section */
+                               sa,             # long int       s_vaddr;  /* Virtual address of section */
+                               s.size, # long int       s_size;   /* Section size in bytes */
+                               sptr,   # long int       s_scnptr; /* File pointer to raw data */
+                               0,              # long int       s_relptr; /* File pointer to relocation entries */
+                               0,              # long int       s_lnnoptr;/* File pointer to line number entries */
+                               0,              # unsigned short s_nreloc; /* Number of relocation entrie */
+                               0,              # unsigned short s_nlnno;  /* Number of line number entries */
+                               s.flags,# unsigned short s_flags;  /* Flags (see ``Section header flags'') */
+                               '\x00', # /
+                               chr(mp),# char           s_mempage;/* Memory page number */
+                       ))
+
+                       # Data
+                       if s.data:
+                               sd.append(self._data_pack(s.data))
+                               dptr += s.size * 2
+
+               # Write the thing
+               f = open(filename, 'wb')
+
+               f.write(fh)
+               f.write(oh)
+               f.write(''.join(sh))
+               f.write(''.join(sd))
+
+               f.close()
+
+       def add_section(self, name, type, addr, size, data=None):
+               self.sections[name] = Section(name, type, addr, size, data=data)
+
+
+# ----------------------------------------------------------------------------
+# Dump loading
+# ----------------------------------------------------------------------------
+
+RE_DUMP_HDR = re.compile(
+       r"^DSP dump: (\w*) \[([0-9a-fA-F]{5})-([0-9a-fA-F]{5})\]$"
+)
+
+
+def _file_strip_gen(f):
+       while True:
+               l = f.readline()
+               if not l:
+                       return
+               yield l.strip()
+
+
+def dump_load_section(fg, sa, ea):
+       data = []
+       ca = sa
+       for l in fg:
+               if not l:
+                       break
+
+               ra = int(l[0:5], 16)
+               if ra != ca:
+                       raise ValueError('Invalid dump address %05x != %05x', ra, ca)
+
+               v = l[8:].split()
+               if len(v) != 16:
+                       raise ValueError('Invalid dump format')
+
+               v = [int(x,16) for x in v]
+               data.extend(v)
+
+               ca += 0x10
+
+       if ca != ea:
+               raise ValueError('Missing dump data %05x != %05x', ra, ea)
+
+       return data
+
+
+def dump_load(filename):
+       # Open file
+       f = open(filename, 'r')
+       fg = _file_strip_gen(f)
+
+       # Scan line by line for a dump header line
+       sections = []
+
+       for l in fg:
+               m = RE_DUMP_HDR.match(l)
+               if not m:
+                       continue
+
+               name = m.group(1)
+               sa   = int(m.group(2), 16)
+               ea   = int(m.group(3), 16) + 1
+
+               sections.append((
+                       name, sa, ea,
+                       dump_load_section(fg, sa, ea),
+               ))
+
+       # Done
+       f.close()
+
+       return sections
+
+
+# ----------------------------------------------------------------------------
+# Main
+# ----------------------------------------------------------------------------
+
+def main(pname, dump_filename, out_filename):
+
+       # Section to place in the COFF
+       sections = [
+               # name                  type          start    size
+               ('.regs',               Section.DATA, 0x00000, 0x0060),
+               ('.scratch',    Section.DATA, 0x00060, 0x0020),
+               ('.drom',               Section.DATA, 0x09000, 0x5000),
+               ('.pdrom',              Section.CODE, 0x0e000, 0x2000),
+               ('.prom0',              Section.CODE, 0x07000, 0x7000),
+               ('.prom1',              Section.CODE, 0x18000, 0x8000),
+               ('.prom2',              Section.CODE, 0x28000, 0x8000),
+               ('.prom3',              Section.CODE, 0x38000, 0x2000),
+               ('.daram0',             Section.DATA, 0x00080, 0x0780),
+               ('.api',                Section.DATA, 0x00800, 0x2000),
+               ('.daram1',             Section.DATA, 0x02800, 0x4800),
+       ]
+
+       # COFF name -> dump name
+       dump_mapping = {
+               # '.regs' :     'Registers',
+               '.drom' :       'DROM',
+               '.pdrom' :      'PDROM',
+               '.prom0' :      'PROM0',
+               '.prom1' :      'PROM1',
+               '.prom2' :      'PROM2',
+               '.prom3' :      'PROM3',
+       }
+
+       # Load the dump
+       dump_sections = dict([(s[0], s) for s in dump_load(dump_filename)])
+
+       # Create the COFF
+       coff = CalypsoCOFF()
+
+       # Add each section (with data if we have some)
+       for name, type, start, size in sections:
+               # Dumped data ?
+               d_data = None
+               if (name in dump_mapping) and (dump_mapping[name] in dump_sections):
+                       d_name, d_sa, d_ea, d_data = dump_sections[dump_mapping[name]]
+
+               # Add sections
+               coff.add_section(name, type, start, size, d_data)
+
+       # Save result
+       coff.save(out_filename)
+
+       return 0
+
+
+if __name__ == '__main__':
+       sys.exit(main(*sys.argv))
diff --git a/src/target_dsp/calypso/ida/README.txt b/src/target_dsp/calypso/ida/README.txt
new file mode 100644 (file)
index 0000000..a793908
--- /dev/null
@@ -0,0 +1,73 @@
+Here's a few steps to get started quickly and get something readable:
+
+ - Compile a patched for the IDA TMS320C54 module
+
+   I made several enhancement to it to support the calypso better (the tms320c54
+   module is part of the SDK and can be modded and recompiled) :
+
+   - Add support for memory mappings so that the same memory zone can
+     'appear' at several place in the address space (to handle data & code
+                overlay)
+   - Fix the section handling when loading a file:
+     . to set XPC properly,
+     . to not override section name
+     . to support more than 2 sections
+   - Fix a bug in cross reference detection when dealing with section
+     having selectors != 0
+   - Add stub support for the type system. This allows loading of a .h
+     header file with the NDB structure definition
+   - Add definition for the IO ports so that they are symbolically
+     displayed
+
+   I can't publically distribute the IDA processor module modification
+   because even just the patch contains some hex-rays code, so I'll handle
+   this on a case by case basis. (just ask me privately and we'll work it out)
+
+ - Dump the DSP ROM
+
+   Using the compal_dsp_dump.bin, you must create a text dump of the DSP ROM,
+   just piping the console output to a text file.
+
+ - Generate COFF image
+
+   The dump2coff.py script can convert the text dump into a usable COFF file
+   containing all the correct sections and addresses.
+
+ - Load this COFF image into IDA
+
+   In the load dialog make sure :
+    - Uncheck the 'Fill segment gaps (COFF)' checkbox
+    - Select 'TMS320C54' in 'Change processor'
+    - In 'Analysis Options/Processor specific analysis options' :
+      - 'Choose device name': CALYPSO
+      - 'Data segment address': 0x80000000
+      - 'Add mapping' (do it several time)
+        - From 0x00000060 -> 0x80000060  size 0x6FA0
+        - From 0x00010060 -> 0x80000060  size 0x6FA0
+        - From 0x00020060 -> 0x80000060  size 0x6FA0
+        - From 0x00030060 -> 0x80000060  size 0x6FA0
+        - From 0x8000E000 -> 0x0000E000  size 0x2000
+
+ - Set 'stub' compiler options to allow the type system to load .h files
+
+   In 'Options/Compiler':
+     - Compiler: 'GNU C++'
+     - Calling convention: 'Cdecl'
+     - Memory model: 'Code Near, Data Near'
+     - Pointer size: 'Near 16bit, Far 32bit'
+     - Include directory: '/usr/include' (or a directory with your includes
+       ... needs to exist)
+
+ - Load the NDB types
+
+   - Load the ndb.h file
+   - In the local types view, import all structure / enum into the database
+   - Then declare the following symbol and set them as struct type
+     appropriately.
+
+     0x80000800 api_w_page_0   db_mcu_to_dsp
+     0x80000814 api_w_page_1   db_mcu_to_dsp
+     0x80000828 api_r_page_0   db_dsp_to_mcu
+     0x8000083c api_r_page_1   db_dsp_to_mcu
+     0x800008d4 ndb            ndb_mcu_dsp
+
diff --git a/src/target_dsp/calypso/ida/ndb.h b/src/target_dsp/calypso/ida/ndb.h
new file mode 100644 (file)
index 0000000..ad9c105
--- /dev/null
@@ -0,0 +1,294 @@
+typedef unsigned char API;
+typedef signed char API_SIGNED;
+
+struct db_mcu_to_dsp
+{
+       API d_task_d;
+       API d_burst_d;
+       API d_task_u;
+       API d_burst_u;
+       API d_task_md;
+       API d_background;
+       API d_debug;
+       API d_task_ra;
+       API d_fn;
+       API d_ctrl_tch;
+       API hole;
+       API d_ctrl_abb;
+       API a_a5fn[2];
+       API d_power_ctl;
+       API d_afc;
+       API d_ctrl_system;
+};
+
+struct db_dsp_to_mcu
+{
+       API d_task_d;
+       API d_burst_d;
+       API d_task_u;
+       API d_burst_u;
+       API d_task_md;
+       API d_background;
+       API d_debug;
+       API d_task_ra;
+       API a_serv_demod[4];
+       API a_pm[3];
+       API a_sch[5];
+};
+
+struct param_mcu_dsp
+{
+       API_SIGNED d_transfer_rate;
+       API_SIGNED d_lat_mcu_bridge;
+       API_SIGNED d_lat_mcu_hom2sam;
+       API_SIGNED d_lat_mcu_bef_fast_access;
+       API_SIGNED d_lat_dsp_after_sam;
+       API_SIGNED d_gprs_install_address;
+       API_SIGNED d_misc_config;
+       API_SIGNED d_cn_sw_workaround;
+       API_SIGNED d_hole2_param[4];
+       API_SIGNED d_fb_margin_beg;
+       API_SIGNED d_fb_margin_end;
+       API_SIGNED d_nsubb_idle;
+       API_SIGNED d_nsubb_dedic;
+       API_SIGNED d_fb_thr_det_iacq;
+       API_SIGNED d_fb_thr_det_track;
+       API_SIGNED d_dc_off_thres;
+       API_SIGNED d_dummy_thres;
+       API_SIGNED d_dem_pond_gewl;
+       API_SIGNED d_dem_pond_red;
+       API_SIGNED d_maccthresh1;
+       API_SIGNED d_mldt;
+       API_SIGNED d_maccthresh;
+       API_SIGNED d_gu;
+       API_SIGNED d_go;
+       API_SIGNED d_attmax;
+       API_SIGNED d_sm;
+       API_SIGNED d_b;
+       API_SIGNED d_v42b_switch_hyst;
+       API_SIGNED d_v42b_switch_min;
+       API_SIGNED d_v42b_switch_max;
+       API_SIGNED d_v42b_reset_delay;
+       API_SIGNED d_ldT_hr;
+       API_SIGNED d_maccthresh_hr;
+       API_SIGNED d_maccthresh1_hr;
+       API_SIGNED d_gu_hr;
+       API_SIGNED d_go_hr;
+       API_SIGNED d_b_hr;
+       API_SIGNED d_sm_hr;
+       API_SIGNED d_attmax_hr;
+       API_SIGNED c_mldt_efr;
+       API_SIGNED c_maccthresh_efr;
+       API_SIGNED c_maccthresh1_efr;
+       API_SIGNED c_gu_efr;
+       API_SIGNED c_go_efr;
+       API_SIGNED c_b_efr;
+       API_SIGNED c_sm_efr;
+       API_SIGNED c_attmax_efr;
+       API_SIGNED d_sd_min_thr_tchfs;
+       API_SIGNED d_ma_min_thr_tchfs;
+       API_SIGNED d_md_max_thr_tchfs;
+       API_SIGNED d_md1_max_thr_tchfs;
+       API_SIGNED d_sd_min_thr_tchhs;
+       API_SIGNED d_ma_min_thr_tchhs;
+       API_SIGNED d_sd_av_thr_tchhs;
+       API_SIGNED d_md_max_thr_tchhs;
+       API_SIGNED d_md1_max_thr_tchhs;
+       API_SIGNED d_sd_min_thr_tchefs;
+       API_SIGNED d_ma_min_thr_tchefs;
+       API_SIGNED d_md_max_thr_tchefs;
+       API_SIGNED d_md1_max_thr_tchefs;
+       API_SIGNED d_wed_fil_ini;
+       API_SIGNED d_wed_fil_tc;
+       API_SIGNED d_x_min;
+       API_SIGNED d_x_max;
+       API_SIGNED d_slope;
+       API_SIGNED d_y_min;
+       API_SIGNED d_y_max;
+       API_SIGNED d_wed_diff_threshold;
+       API_SIGNED d_mabfi_min_thr_tchhs;
+       API_SIGNED d_facch_thr;
+       API_SIGNED d_max_ovsp_ul;
+       API_SIGNED d_sync_thres;
+       API_SIGNED d_idle_thres;
+       API_SIGNED d_m1_thres;
+       API_SIGNED d_max_ovsp_dl;
+       API_SIGNED d_gsm_bgd_mgt;
+       API a_fir_holes[4];
+       API a_fir31_uplink[31];
+       API a_fir31_downlink[31];
+};
+
+struct ndb_mcu_dsp
+{
+       API d_dsp_page;
+       API d_error_status;
+       API d_spcx_rif;
+       API d_tch_mode;
+       API d_debug1;
+       API d_dsp_test;
+       API d_version_number1;
+       API d_version_number2;
+       API d_debug_ptr;
+       API d_debug_bk;
+       API d_pll_config;
+       API p_debug_buffer;
+       API d_debug_buffer_size;
+       API d_debug_trace_type;
+       API d_dsp_state;
+       API d_hole1_ndb[2];
+       API d_hole_debug_amr;
+       API d_hole2_ndb[1];
+       API d_mcsi_select;
+       API d_apcdel1_bis;
+       API d_apcdel2_bis;
+       API d_apcdel2;
+       API d_vbctrl2;
+       API d_bulgcal;
+       API d_afcctladd;
+       API d_vbuctrl;
+       API d_vbdctrl;
+       API d_apcdel1;
+       API d_apcoff;
+       API d_bulioff;
+       API d_bulqoff;
+       API d_dai_onoff;
+       API d_auxdac;
+       API d_vbctrl1;
+       API d_bbctrl;
+       API d_fb_det;
+       API d_fb_mode;
+       API a_sync_demod[4];
+       API a_sch26[5];
+       API d_audio_gain_ul;
+       API d_audio_gain_dl;
+       API d_audio_compressor_ctrl;
+       API d_audio_init;
+       API d_audio_status;
+       API d_toneskb_init;
+       API d_toneskb_status;
+       API d_k_x1_t0;
+       API d_k_x1_t1;
+       API d_k_x1_t2;
+       API d_pe_rep;
+       API d_pe_off;
+       API d_se_off;
+       API d_bu_off;
+       API d_t0_on;
+       API d_t0_off;
+       API d_t1_on;
+       API d_t1_off;
+       API d_t2_on;
+       API d_t2_off;
+       API d_k_x1_kt0;
+       API d_k_x1_kt1;
+       API d_dur_kb;
+       API d_shiftdl;
+       API d_shiftul;
+       API d_aec_ctrl;
+       API d_es_level_api;
+       API d_mu_api;
+       API d_melo_osc_used;
+       API d_melo_osc_active;
+       API a_melo_note0[4];
+       API a_melo_note1[4];
+       API a_melo_note2[4];
+       API a_melo_note3[4];
+       API a_melo_note4[4];
+       API a_melo_note5[4];
+       API a_melo_note6[4];
+       API a_melo_note7[4];
+       API d_melody_selection;
+       API a_melo_holes[3];
+       API d_sr_status;
+       API d_sr_param;
+       API d_sr_bit_exact_test;
+       API d_sr_nb_words;
+       API d_sr_db_level;
+       API d_sr_db_noise;
+       API d_sr_mod_size;
+       API a_n_best_words[4];
+       API a_n_best_score[8];
+       API a_dd_1[22];
+       API a_du_1[22];
+       API d_v42b_nego0;
+       API d_v42b_nego1;
+       API d_v42b_control;
+       API d_v42b_ratio_ind;
+       API d_mcu_control;
+       API d_mcu_control_sema;
+       API d_background_enable;
+       API d_background_abort;
+       API d_background_state;
+       API d_max_background;
+       API a_background_tasks[16];
+       API a_back_task_io[16];
+       API d_gea_mode_ovly;
+       API a_gea_kc_ovly[4];
+       API d_hole3_ndb[7];
+       API d_thr_usf_detect;
+       API d_a5mode;
+       API d_sched_mode_gprs_ovly;
+       API d_hole4_ndb[5];
+       API a_ramp[16];
+       API a_cd[15];
+       API a_fd[15];
+       API a_dd_0[22];
+       API a_cu[15];
+       API a_fu[15];
+       API a_du_0[22];
+       API d_rach;
+       API a_kc[4];
+       API d_ra_conf;
+       API d_ra_act;
+       API d_ra_test;
+       API d_ra_statu;
+       API d_ra_statd;
+       API d_fax;
+       API a_data_buf_ul[21];
+       API a_data_buf_dl[37];
+       API a_tty_holes[8];
+       API a_sr_holes0[414];
+       API a_new_aec_holes[12];
+       // API a_sr_holes1[145];
+       struct param_mcu_dsp params;
+       API d_cport_init;
+       API d_cport_ctrl;
+       API a_cport_cfr[2];
+       API d_cport_tcl_tadt;
+       API d_cport_tdat;
+       API d_cport_tvs;
+       API d_cport_status;
+       API d_cport_reg_value;
+       API a_cport_holes[1011];
+       API a_model[1041];
+       API a_eotd_holes[22];
+       API a_amr_config[4];
+       API a_ratscch_ul[6];
+       API a_ratscch_dl[6];
+       API d_amr_snr_est;
+       API a_voice_memo_amr_holes[1];
+       API d_thr_onset_afs;
+       API d_thr_sid_first_afs;
+       API d_thr_ratscch_afs;
+       API d_thr_update_afs;
+       API d_thr_onset_ahs;
+       API d_thr_sid_ahs;
+       API d_thr_ratscch_marker;
+       API d_thr_sp_dgr;
+       API d_thr_soft_bits;
+       API d_holes[61];
+};
+
+enum dsp_error {
+       DSP_ERR_RHEA            = 0x0001,
+       DSP_ERR_IQ_SAMPLES      = 0x0004,
+       DSP_ERR_DMA_PROG        = 0x0008,
+       DSP_ERR_DMA_TASK        = 0x0010,
+       DSP_ERR_DMA_PEND        = 0x0020,
+       DSP_ERR_VM              = 0x0080,
+       DSP_ERR_DMA_UL_TASK     = 0x0100,
+       DSP_ERR_DMA_UL_PROG     = 0x0200,
+       DSP_ERR_DMA_UL_PEND     = 0x0400,
+       DSP_ERR_STACK_OV        = 0x0800,
+};
diff --git a/src/target_dsp/calypso/ida/tms320c54.cfg b/src/target_dsp/calypso/ida/tms320c54.cfg
new file mode 100644 (file)
index 0000000..7962bee
--- /dev/null
@@ -0,0 +1,136 @@
+; Append this to the tms320c54.cfg shipped with IDA\r
+\r
+.CALYPSO\r
+\r
+; entry _reset 0xff80 Reset vector\r
+\r
+;      RIF\r
+RIF_DXR                        0x0000\r
+RIF_DRR                        0x0001\r
+RIF_SPCX               0x0002\r
+RIF_SPCR               0x0003\r
+\r
+;      CYPHER\r
+CYPHER_CNTL            0x2800\r
+CYPHER_CNTL.START                      0\r
+CYPHER_CNTL.RESETSW                    1\r
+CYPHER_CNTL.MODE0                      2\r
+CYPHER_CNTL.MODE1                      3\r
+CYPHER_CNTL.CLK_EN                     4\r
+CYPHER_CNTL.CYPHER_ONLY                        5\r
+\r
+CYPHER_STATUS_IRQ      0x2801\r
+CYPHER_STATUS_IRQ.LT_FIN               0\r
+\r
+CYPHER_STATUS_WORK     0x2802\r
+CYPHER_STATUS_WORK.WORKING             0\r
+\r
+CYPHER_KC_1            0x2803\r
+CYPHER_KC_2            0x2804\r
+CYPHER_KC_3            0x2805\r
+CYPHER_KC_4            0x2806\r
+CYPHER_COUNT_1         0x2807\r
+CYPHER_COUNT_2         0x2808\r
+CYPHER_DECI_1          0x2809\r
+CYPHER_DECI_2          0x280A\r
+CYPHER_DECI_3          0x280B\r
+CYPHER_DECI_4          0x280C\r
+CYPHER_DECI_5          0x280D\r
+CYPHER_DECI_6          0x280E\r
+CYPHER_DECI_7          0x280F\r
+CYPHER_DECI_8          0x2810\r
+CYPHER_ENCI_1          0x2811\r
+CYPHER_ENCI_2          0x2812\r
+CYPHER_ENCI_3          0x2813\r
+CYPHER_ENCI_4          0x2814\r
+CYPHER_ENCI_5          0x2815\r
+CYPHER_ENCI_6          0x2816\r
+CYPHER_ENCI_7          0x2817\r
+CYPHER_ENCI_8          0x2818\r
+\r
+;      MCSI\r
+MCSI_CONTROL           0x0800\r
+MCSI_MAIN-PARAMETERS   0x0801\r
+MCSI_INTERRUPTS                0x0802\r
+MCSI_CHANNEL-USED      0x0803\r
+MCSI_OVER-CLK          0x0804\r
+MCSI_CLK-FREQ          0x0805\r
+MCSI_STATUS            0x0806\r
+MCSI_TX0               0x0820\r
+MCSI_TX1               0x0821\r
+MCSI_TX2               0x0822\r
+MCSI_TX3               0x0823\r
+MCSI_TX4               0x0824\r
+MCSI_TX5               0x0825\r
+MCSI_TX6               0x0826\r
+MCSI_TX7               0x0827\r
+MCSI_TX8               0x0828\r
+MCSI_TX9               0x0829\r
+MCSI_TX10              0x082A\r
+MCSI_TX11              0x082B\r
+MCSI_TX12              0x082C\r
+MCSI_TX13              0x082D\r
+MCSI_TX14              0x082E\r
+MCSI_TX15              0x082F\r
+MCSI_RX0               0x0830\r
+MCSI_RX1               0x0831\r
+MCSI_RX2               0x0832\r
+MCSI_RX3               0x0833\r
+MCSI_RX4               0x0834\r
+MCSI_RX5               0x0835\r
+MCSI_RX6               0x0836\r
+MCSI_RX7               0x0837\r
+MCSI_RX8               0x0838\r
+MCSI_RX9               0x0839\r
+MCSI_RX10              0x083A\r
+MCSI_RX11              0x083B\r
+MCSI_RX12              0x083C\r
+MCSI_RX13              0x083D\r
+MCSI_RX14              0x083E\r
+MCSI_RX15              0x083F\r
+\r
+;      RHEA\r
+RHEA_TRANSFER_RATE     0xF800\r
+\r
+RHEA_BRIDGE-CTRL       0xF801\r
+RHEA_BRIDGE-CTRL.TIMEOUT_ENABLE                8\r
+RHEA_BRIDGE-CTRL.NSUPV                 9\r
+\r
+;      API\r
+API_CONF               0xF900\r
+API_CONF.RESERVED0                     0\r
+API_CONF.API_HOM                       1\r
+API_CONF.BRIDGE_CLK_EN                 2\r
+\r
+;      Interrupts\r
+INT_CNTRL              0xFA00\r
+INT_CLEAR              0xFA01\r
+\r
+;      DMA\r
+DMA_CONTROLLER_CONF    0xFC00\r
+DMA_ALLOC_CONFIG       0xFC02\r
+DMA1_RAD               0xFC10\r
+DMA1_RDPTH             0xFC12\r
+DMA1_AAD               0xFC14\r
+DMA1_ALGTH             0xFC16\r
+DMA1_CTRL              0xFC18\r
+DMA1_CUR_OFFSET_API    0xFC1A\r
+DMA2_RAD               0xFC20\r
+DMA2_RDPTH             0xFC22\r
+DMA2_AAD               0xFC24\r
+DMA2_ALGTH             0xFC26\r
+DMA2_CTRL              0xFC28\r
+DMA2_CUR_OFFSET_API    0xFC2A\r
+DMA3_RAD               0xFC30\r
+DMA3_RDPTH             0xFC32\r
+DMA3_AAD               0xFC34\r
+DMA3_ALGTH             0xFC36\r
+DMA3_CTRL              0xFC38\r
+DMA3_CUR_OFFSET_API    0xFC3A\r
+DMA4_RAD               0xFC40\r
+DMA4_RDPTH             0xFC42\r
+DMA4_AAD               0xFC44\r
+DMA4_ALGTH             0xFC46\r
+DMA4_CTRL              0xFC48\r
+DMA4_CUR_OFFSET_API    0xFC4A\r
+\r