KM3NeT CLB  2.0
KM3NeT CLB v2 Embedded Software
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
sdb.c
1 /*
2  * KM3NeT CLB v2 Firmware
3  * ----------------------
4  *
5  * Copyright 2013 National Institute for Subatomic Physics Nikhef
6  *
7  * All Rights Reserved.
8  *
9  *
10  * File : sdb.c
11  * Created : 5 jul. 2013
12  * Author : Vincent van Beveren
13  */
14 
15 #include <stdint.h>
16 #include <stdio.h>
17 
18 #include "lm32soc/dev_soc.h"
19 
20 #include "kernel/err.h"
21 #include "drv/wb/sdb.h"
22 
23 
24 
25 #define _SDB_MAGIC 0x5344422d /* "SDB-" */
26 
27 
28 typedef struct
29 {
30  uint32_t high;
31  uint32_t low;
32 } U32Pair;
33 
34 enum SdbBusType {
35  sdbBusTypeWishbone = 0x00
36 };
37 
38 #define SDB_WB_WIDTH_MASK 0x0f
39 #define SDB_WB_ACCESS8 0x01
40 #define SDB_WB_ACCESS16 0x02
41 #define SDB_WB_ACCESS32 0x04
42 #define SDB_WB_ACCESS64 0x08
43 #define SDB_WB_LITTLE_ENDIAN 0x80
44 
45 /* Type of the SDB record */
46 typedef enum {
47  sdbTypeInterconnect = 0x00,
48  sdbTypeDevice = 0x01,
49  sdbTypeBridge = 0x02,
50  sdbTypeIntegration = 0x80,
51  sdbTypeEmpty = 0xFF
52 } SdbRecordType;
53 
54 typedef struct {
55  U32Pair vendorId;
56  uint32_t deviceId;
57  uint32_t version;
58  uint32_t date;
59  uint8_t name[19];
60  uint8_t recordType;
61 } SdbProduct;
62 
63 typedef struct {
64  U32Pair addrFirst;
65  U32Pair addrLast;
66  SdbProduct product;
67 } SdbComponent;
68 
69 typedef struct
70 {
71  uint32_t magic;
72  uint16_t records;
73  uint8_t version;
74  uint8_t busType;
75  SdbComponent component;
77 
78 typedef struct
79 {
80  uint16_t abiClass;
81  uint8_t abiVerMajor;
82  uint8_t abiVerMinor;
83  uint32_t busSpecific;
84  SdbComponent component;
85 } SdbDevice;
86 
87 typedef struct
88 {
89  U32Pair child;
90  SdbComponent component;
91 } SdbBridge;
92 
93 typedef struct
94 {
95  uint8_t reserved[24];
96  SdbProduct product;
98 
99 typedef struct
100 {
101  uint8_t reserved[63];
102  uint8_t recordType;
103 } SdbEntry;
104 
105 static const SdbInterconnect * const _sdbRoot = (const SdbInterconnect * const)SDB;
106 
107 #define _MAX_SCAN_DEPTH 3
108 
109 static const SdbInterconnect * _stack[_MAX_SCAN_DEPTH];
110 static int _stackIdx = 0;
111 static char _spaces[_MAX_SCAN_DEPTH + 1];
112 static uint32_t _addrOffset = 0;
113 
114 static void sdbDisplaySdbArray(const SdbInterconnect * ic);
115 
116 
117 static bool sdbIcPush(const SdbInterconnect * ic)
118 {
119  if (_stackIdx == _MAX_SCAN_DEPTH) return false;
120  int i = 0;
121  for (i = 0; i < _stackIdx; ++i) {
122  if (_stack[i] == ic) return false;
123  }
124  _spaces[_stackIdx] = '\t';
125  _stack[_stackIdx++] = ic;
126  _spaces[_stackIdx] = '\0';
127  return true;
128 }
129 
130 static void sdbIcPop()
131 {
132  _stackIdx--;
133  _spaces[_stackIdx] = '\0';
134 }
135 
136 #define sdb_printf(STR, ...) \
137  printf("%s" STR, _spaces, __VA_ARGS__)
138 
139 #define DEVICE_TYPE(PTR) \
140  (((uint8_t *)ptr)[63])
141 
142 static void sdbDisplayProduct(const SdbProduct * prodPtr)
143 {
144  char name[20];
145  memcpy(name, prodPtr->name, 19);
146  name[19] = '\0';
147  sdb_printf(" DeviceId : %08lx\n", prodPtr->deviceId);
148 #ifdef SDB_VERBOSE
149  sdb_printf(" VendorId : %08lx:%08lx\n", prodPtr->vendorId.high, prodPtr->vendorId.low);
150  sdb_printf(" Date : %x\n", prodPtr->date);
151  sdb_printf(" Version : %d\n", prodPtr->version);
152 #endif
153  sdb_printf(" Name : %s\n", name);
154 }
155 
156 static void sdbDisplayComponent(const SdbComponent * compPtr)
157 {
158 #ifdef SDB_VERBOSE
159  sdb_printf(" AddrFirst : %08lx:%08lx\n", compPtr->addrFirst.high, compPtr->addrFirst.low + _addrOffset);
160  sdb_printf(" AddrLast : %08lx:%08lx\n", compPtr->addrLast.high, compPtr->addrLast.low + _addrOffset);
161 #else
162  sdb_printf(" AddrRange : %08lx-%08lx\n", compPtr->addrFirst.low + _addrOffset, compPtr->addrLast.low + _addrOffset);
163 #endif
164  sdbDisplayProduct(&(compPtr->product));
165 }
166 
167 static void sdbDisplayDevice(const SdbDevice * devPtr)
168 {
169 #ifdef SDB_VERBOSE
170  sdb_printf(" ABI Class : %04x\n", devPtr->abiClass);
171  sdb_printf(" ABI Version: %d.%d\n", devPtr->abiVerMajor, devPtr->abiVerMinor);
172  sdb_printf(" Bus Spec. : %08lx\n", devPtr->busSpecific);
173 #endif
174  sdbDisplayComponent(&(devPtr->component));
175 }
176 
177 static void sdbDisplayBridge(const SdbBridge * brdgPtr)
178 {
179 #ifdef SDB_VERBOSE
180  sdb_printf(" Child : %08x:%08x\n", brdgPtr->child.high, brdgPtr->child.low + _addrOffset);
181 #endif
182  sdbDisplayComponent(&(brdgPtr->component));
183  // for now I don't think a 64 bit processor is forseen.
184  uint32_t icAddr = brdgPtr->child.low + _addrOffset;
185  uint32_t offset = brdgPtr->component.addrFirst.low;
186 
187  sdb_printf("** icAddress: %08lx \n", icAddr);
188 
189 
190  _addrOffset += offset;
191 
192  // NASTY TRICKSY! BAD HOBBITS!
193  if (icAddr < _addrOffset)
194  {
195  icAddr += offset;
196  }
197 
198 
199 
200  sdb_printf("** Following interconnect at %08lx, offset at %08lx **\n", icAddr, _addrOffset);
201 
202  sdbDisplaySdbArray((const SdbInterconnect *)icAddr);
203 
204  _addrOffset -= offset;
205 
206 }
207 
208 
209 static void sdbDisplayInterconnect(const SdbInterconnect * ptr)
210 {
211 #ifdef SDB_VERBOSE
212  sdb_printf(" Magic : %08lx\n", ptr->magic);
213  sdb_printf(" Version : %u\n", ptr->version);
214  sdb_printf(" BusType : %u\n", ptr->busType);
215 #endif
216  sdb_printf(" Records : %u\n", ptr->records);
217 
218  sdbDisplayComponent(&(ptr->component));
219 }
220 
221 static void sdbDisplaySdbEntry(const SdbEntry * entryPtr)
222 {
223 
224  sdb_printf("Device (addr = %08x, type = ", entryPtr);
225  switch (entryPtr->recordType)
226  {
227  case sdbTypeInterconnect:
228  puts("Interconnect):");
229  sdbDisplayInterconnect((SdbInterconnect *)entryPtr);
230  break;
231  case sdbTypeDevice:
232  puts("Device):");
233  sdbDisplayDevice((SdbDevice *)entryPtr);
234  break;
235  case sdbTypeBridge:
236  puts("Bridge):");
237  sdbDisplayBridge((SdbBridge *)entryPtr);
238  break;
239  default:
240  printf("Unknown/Unsupported #%d )\n", entryPtr->recordType);
241  break;
242  }
243  puts("");
244 }
245 
246 static void sdbDisplaySdbArray(const SdbInterconnect * ic)
247 {
248  if (!sdbIcPush(ic)) {
249  return;
250  }
251 
252  if (ic->magic != _SDB_MAGIC) {
253  sdbIcPop();
254  puts("Can't display array, interconnect invalid!");
255  return;
256  }
257 
258  int i;
259  SdbEntry * current = (SdbEntry *)ic;
260 
261  for (i = 0; i < ic->records; ++i, ++current)
262  {
263  sdbDisplaySdbEntry(current);
264  }
265 
266  sdbIcPop();
267 
268 }
269 
270 static void * sdbFindDeviceDeep(const SdbInterconnect * ic, uint32_t id, int maxdepth)
271 {
272  SdbEntry * current = (SdbEntry *)ic;
273  SdbDevice * devPtr;
274  void * ptr;
275  const SdbInterconnect * ic2;
276  int i;
277 
278  for (i = 0; i < ic->records; ++i, ++current)
279  {
280  switch (current->recordType)
281  {
282  case sdbTypeDevice:
283  devPtr = (SdbDevice *)current;
284  if (devPtr->component.product.deviceId == id)
285  {
286  return (void *)(devPtr->component.addrFirst.low);
287  }
288  break;
289  case sdbTypeBridge:
290  if (maxdepth == 0) continue;
291  ic2 = (SdbInterconnect *)(( SdbBridge *)current)->child.low + _addrOffset;
292  ptr = sdbFindDeviceDeep(ic2, id, maxdepth - 1);
293  if (ptr != NULL) return ptr;
294  break;
295  default:
296  break;
297  }
298 
299  }
300  return NULL;
301 
302 }
303 
304 
305 void * sdbFindDevice(uint32_t id)
306 {
307  return sdbFindDeviceDeep(_sdbRoot, id, 2);
308 }
309 
310 bool sdbInit()
311 {
312  if (_sdbRoot->magic != _SDB_MAGIC)
313  {
315  return false;
316  }
317  _spaces[0] = '\0';
318  // sdbDisplaySdbArray(_sdbRoot);
319 
320  return true;
321 }
322 
324 {
325  sdbDisplaySdbArray(_sdbRoot);
326 }
Implements search functionality for the self-describing bus.
Definition: sdb.c:87
Definition: sdb.c:78
Definition: sdb.c:54
#define E_SDB_MAGIC
Magic number incorrect.
Definition: sdb.h:31
void * sdbFindDevice(uint32_t id)
Finds a device on the bus.
Definition: sdb.c:305
Definition: sdb.c:99
bool sdbInit()
Initializes the self-describing bus.
Definition: sdb.c:310
Definition: sdb.c:28
Manages the global system error.
void sdbDisplay()
Dumps the contents of the SDB records to standard out.
Definition: sdb.c:323
#define SDB
Self Describing Bus.
Definition: dev_soc.h:56
This file assigns all device structures to memory mapped structures.
bool errSet(uint32_t code, const char *error, const char *name)
Sets an error.
#define ERROR(CODE,...)
Expands an error code to an error code with a description (if ERROR_W_DESCR is declared).