sdb.c 3.66 KB
Newer Older
1 2 3 4 5 6 7 8
/*
 * This work is part of the White Rabbit project
 *
 * Copyright (C) 2012 GSI (www.gsi.de)
 * Author: Wesley W. Terpstra <w.terpstra@gsi.de>
 *
 * Released according to the GNU GPL, version 2 or any later version.
 */
9 10
#include <string.h>
#include <wrc.h>
11 12
#include "hw/memlayout.h"

13 14 15 16 17 18 19 20 21
unsigned char *BASE_MINIC;
unsigned char *BASE_EP;
unsigned char *BASE_SOFTPLL;
unsigned char *BASE_PPS_GEN;
unsigned char *BASE_SYSCON;
unsigned char *BASE_UART;
unsigned char *BASE_ONEWIRE;
unsigned char *BASE_ETHERBONE_CFG;

22 23 24 25 26 27
#define SDB_INTERCONNET 0x00
#define SDB_DEVICE      0x01
#define SDB_BRIDGE      0x02
#define SDB_EMPTY       0xFF

typedef struct pair64 {
28 29
	uint32_t high;
	uint32_t low;
30 31 32
} pair64_t;

struct sdb_empty {
33 34
	int8_t reserved[63];
	uint8_t record_type;
35 36 37
};

struct sdb_product {
38 39 40 41 42 43
	pair64_t vendor_id;
	uint32_t device_id;
	uint32_t version;
	uint32_t date;
	int8_t name[19];
	uint8_t record_type;
44 45 46
};

struct sdb_component {
47 48 49
	pair64_t addr_first;
	pair64_t addr_last;
	struct sdb_product product;
50 51 52
};

struct sdb_device {
53 54 55 56 57
	uint16_t abi_class;
	uint8_t abi_ver_major;
	uint8_t abi_ver_minor;
	uint32_t bus_specific;
	struct sdb_component sdb_component;
58 59 60
};

struct sdb_bridge {
61 62
	pair64_t sdb_child;
	struct sdb_component sdb_component;
63 64 65
};

struct sdb_interconnect {
66 67 68 69 70
	uint32_t sdb_magic;
	uint16_t sdb_records;
	uint8_t sdb_version;
	uint8_t sdb_bus_type;
	struct sdb_component sdb_component;
71 72 73
};

typedef union sdb_record {
74 75 76 77
	struct sdb_empty empty;
	struct sdb_device device;
	struct sdb_bridge bridge;
	struct sdb_interconnect interconnect;
78 79
} sdb_record_t;

80 81 82 83 84 85 86 87 88 89 90 91 92
static unsigned char *find_device_deep(unsigned int base, unsigned int sdb,
				       unsigned int devid)
{
	sdb_record_t *record = (sdb_record_t *) sdb;
	int records = record->interconnect.sdb_records;
	int i;

	for (i = 0; i < records; ++i, ++record) {
		if (record->empty.record_type == SDB_BRIDGE) {
			unsigned char *out =
			    find_device_deep(base +
					     record->bridge.sdb_component.
					     addr_first.low,
93
					     base +
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
					     record->bridge.sdb_child.low,
					     devid);
			if (out)
				return out;
		}
		if (record->empty.record_type == SDB_DEVICE &&
		    record->device.sdb_component.product.device_id == devid) {
			break;
		}
	}

	if (i == records)
		return 0;
	return (unsigned char *)(base +
				 record->device.sdb_component.addr_first.low);
109 110
}

111 112 113 114 115 116 117 118 119 120 121 122
static void print_devices_deep(unsigned int base, unsigned int sdb)
{
	sdb_record_t *record = (sdb_record_t *) sdb;
	int records = record->interconnect.sdb_records;
	int i;
	char buf[20];

	for (i = 0; i < records; ++i, ++record) {
		if (record->empty.record_type == SDB_BRIDGE)
			print_devices_deep(base +
					   record->bridge.sdb_component.
					   addr_first.low,
123
					   base +
124 125 126 127 128 129 130 131 132 133 134 135 136
					   record->bridge.sdb_child.low);

		if (record->empty.record_type != SDB_DEVICE)
			continue;

		memcpy(buf, record->device.sdb_component.product.name, 19);
		buf[19] = 0;
		mprintf("%8x:%8x 0x%8x %s\n",
			record->device.sdb_component.product.vendor_id.low,
			record->device.sdb_component.product.device_id,
			base + record->device.sdb_component.addr_first.low,
			buf);
	}
137 138
}

139 140
static unsigned char *find_device(unsigned int devid)
{
141
	return find_device_deep(0, SDB_ADDRESS, devid);
142 143
}

144 145 146 147 148
void sdb_print_devices(void)
{
	mprintf("SDB memory map:\n");
	print_devices_deep(0, SDB_ADDRESS);
	mprintf("---\n");
149 150
}

151 152 153 154 155 156 157 158 159 160
void sdb_find_devices(void)
{
	BASE_MINIC =         find_device(0xab28633a);
	BASE_EP =            find_device(0x650c2d4f);
	BASE_SOFTPLL =       find_device(0x65158dc0);
	BASE_PPS_GEN =       find_device(0xde0d8ced);
	BASE_SYSCON =        find_device(0xff07fc47);
	BASE_UART =          find_device(0xe2d13d04);
	BASE_ONEWIRE =       find_device(0x779c5443);
	BASE_ETHERBONE_CFG = find_device(0x68202b22);
161
}