summaryrefslogtreecommitdiffstats
path: root/src/roms/SLOF/clients/net-snk/app/biosemu/device.h
blob: 425dd3caf35c9741f0f626195ac796e5cb141e6e (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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/******************************************************************************
 * Copyright (c) 2004, 2008 IBM Corporation
 * All rights reserved.
 * This program and the accompanying materials
 * are made available under the terms of the BSD License
 * which accompanies this distribution, and is available at
 * http://www.opensource.org/licenses/bsd-license.php
 *
 * Contributors:
 *     IBM Corporation - initial implementation
 *****************************************************************************/

#ifndef DEVICE_LIB_H
#define DEVICE_LIB_H

#include <stdint.h>
#include <cpu.h>
#include "of.h"
#include <stdio.h>

// a Expansion Header Struct as defined in Plug and Play BIOS Spec 1.0a Chapter 3.2
typedef struct {
	char signature[4];	// signature
	uint8_t structure_revision;
	uint8_t length;		// in 16 byte blocks
	uint16_t next_header_offset;	// offset to next Expansion Header as 16bit little-endian value, as offset from the start of the Expansion ROM
	uint8_t reserved;
	uint8_t checksum;	// the sum of all bytes of the Expansion Header must be 0
	uint32_t device_id;	// PnP Device ID as 32bit little-endian value
	uint16_t p_manufacturer_string;	//16bit little-endian offset from start of Expansion ROM
	uint16_t p_product_string;	//16bit little-endian offset from start of Expansion ROM
	uint8_t device_base_type;
	uint8_t device_sub_type;
	uint8_t device_if_type;
	uint8_t device_indicators;
	// the following vectors are all 16bit little-endian offsets from start of Expansion ROM
	uint16_t bcv;		// Boot Connection Vector
	uint16_t dv;		// Disconnect Vector
	uint16_t bev;		// Bootstrap Entry Vector
	uint16_t reserved_2;
	uint16_t sriv;		// Static Resource Information Vector
} __attribute__ ((__packed__)) exp_header_struct_t;

// a PCI Data Struct as defined in PCI 2.3 Spec Chapter 6.3.1.2
typedef struct {
	uint8_t signature[4];	// signature, the String "PCIR"
	uint16_t vendor_id;
	uint16_t device_id;
	uint16_t reserved;
	uint16_t pci_ds_length;	// PCI Data Structure Length, 16bit little-endian value
	uint8_t pci_ds_revision;
	uint8_t class_code[3];
	uint16_t img_length;	// length of the Exp.ROM Image, 16bit little-endian value in 512 bytes
	uint16_t img_revision;
	uint8_t code_type;
	uint8_t indicator;
	uint16_t reserved_2;
} __attribute__ ((__packed__)) pci_data_struct_t;

typedef struct {
	uint8_t bus;
	uint8_t devfn;
	uint64_t puid;
	phandle_t phandle;
	ihandle_t ihandle;
	// store the address of the BAR that is used to simulate
	// legacy VGA memory accesses
	uint64_t vmem_addr;
	uint64_t vmem_size;
	// used to buffer I/O Accesses, that do not access the I/O Range of the device...
	// 64k might be overkill, but we can buffer all I/O accesses...
	uint8_t io_buffer[64 * 1024];
	uint16_t pci_vendor_id;
	uint16_t pci_device_id;
	// translated address of the "PC-Compatible" Expansion ROM Image for this device
	uint64_t img_addr;
	uint32_t img_size;	// size of the Expansion ROM Image (read from the PCI Data Structure)
} device_t;

typedef struct {
	uint8_t info;
	uint8_t bus;
	uint8_t devfn;
	uint8_t cfg_space_offset;
	uint64_t address;
	uint64_t address_offset;
	uint64_t size;
} __attribute__ ((__packed__)) translate_address_t;

// array to store address translations for this
// device. Needed for faster address translation, so
// not every I/O or Memory Access needs to call translate_address_dev
// and access the device tree
// 6 BARs, 1 Exp. ROM, 1 Cfg.Space, and 3 Legacy
// translations are supported... this should be enough for
// most devices... for VGA it is enough anyways...
translate_address_t translate_address_array[11];

// index of last translate_address_array entry
// set by get_dev_addr_info function
uint8_t taa_last_entry;

device_t bios_device;

uint8_t dev_init(char *device_name);
// NOTE: for dev_check_exprom to work, dev_init MUST be called first!
uint8_t dev_check_exprom(void);

uint8_t dev_translate_address(uint64_t * addr);

/* endianness swap functions for 16 and 32 bit words
 * copied from axon_pciconfig.c
 */
static inline void
out32le(void *addr, uint32_t val)
{
	asm volatile ("stwbrx  %0, 0, %1"::"r" (val), "r"(addr));
}

static inline uint32_t
in32le(void *addr)
{
	uint32_t val;
	const uint32_t *zaddr = addr;
	asm volatile ("lwbrx %0, %y1" : "=r"(val) : "Z"(*zaddr));
	return val;
}

static inline void
out16le(void *addr, uint16_t val)
{
	asm volatile ("sthbrx  %0, 0, %1"::"r" (val), "r"(addr));
}

static inline uint16_t
in16le(void *addr)
{
	uint16_t val;
	const uint16_t *zaddr = addr;
	asm volatile ("lhbrx %0, %y1" : "=r"(val) : "Z"(*zaddr));
	return val;
}

/* debug function, dumps HID1 and HID4 to detect wether caches are on/off */
static inline void
dumpHID(void)
{
	uint64_t hid;
	//HID1 = 1009
	__asm__ __volatile__("mfspr %0, 1009":"=r"(hid));
	printf("HID1: %016llx\n", hid);
	//HID4 = 1012
	__asm__ __volatile__("mfspr %0, 1012":"=r"(hid));
	printf("HID4: %016llx\n", hid);
}

#endif
OpenPOWER on IntegriCloud