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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
|
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation
* Copyright (c) 2008, 2009 Pattrick Hueper <phueper@hueper.net>
* 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 <types.h>
#include <endian.h>
#include "compat/of.h"
#include "debug.h"
// a Expansion Header Struct as defined in Plug and Play BIOS Spec 1.0a Chapter 3.2
typedef struct {
char signature[4]; // signature
u8 structure_revision;
u8 length; // in 16 byte blocks
u16 next_header_offset; // offset to next Expansion Header as 16bit little-endian value, as offset from the start of the Expansion ROM
u8 reserved;
u8 checksum; // the sum of all bytes of the Expansion Header must be 0
u32 device_id; // PnP Device ID as 32bit little-endian value
u16 p_manufacturer_string; //16bit little-endian offset from start of Expansion ROM
u16 p_product_string; //16bit little-endian offset from start of Expansion ROM
u8 device_base_type;
u8 device_sub_type;
u8 device_if_type;
u8 device_indicators;
// the following vectors are all 16bit little-endian offsets from start of Expansion ROM
u16 bcv; // Boot Connection Vector
u16 dv; // Disconnect Vector
u16 bev; // Bootstrap Entry Vector
u16 reserved_2;
u16 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 {
u8 signature[4]; // signature, the String "PCIR"
u16 vendor_id;
u16 device_id;
u16 reserved;
u16 pci_ds_length; // PCI Data Structure Length, 16bit little-endian value
u8 pci_ds_revision;
u8 class_code[3];
u16 img_length; // length of the Exp.ROM Image, 16bit little-endian value in 512 bytes
u16 img_revision;
u8 code_type;
u8 indicator;
u16 reserved_2;
} __attribute__ ((__packed__)) pci_data_struct_t;
typedef struct {
u8 bus;
u8 devfn;
#if CONFIG_PCI_OPTION_ROM_RUN_YABEL
struct device* dev;
#else
u64 puid;
phandle_t phandle;
ihandle_t ihandle;
#endif
// store the address of the BAR that is used to simulate
// legacy VGA memory accesses
u64 vmem_addr;
u64 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...
u8 io_buffer[64 * 1024];
u16 pci_vendor_id;
u16 pci_device_id;
// translated address of the "PC-Compatible" Expansion ROM Image for this device
unsigned long img_addr;
u32 img_size; // size of the Expansion ROM Image (read from the PCI Data Structure)
} biosemu_device_t;
typedef struct {
#if CONFIG_PCI_OPTION_ROM_RUN_YABEL
unsigned long info;
#else
u8 info;
#endif
u8 bus;
u8 devfn;
u8 cfg_space_offset;
u64 address;
u64 address_offset;
u64 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, plus 2 "special"
// translations are supported... this should be enough for
// most devices... for VGA it is enough anyways...
extern translate_address_t translate_address_array[13];
// index of last translate_address_array entry
// set by get_dev_addr_info function
extern u8 taa_last_entry;
// add 1:1 mapped memory regions to translation table
void biosemu_add_special_memory(u32 start, u32 size);
/* the device we are working with... */
extern biosemu_device_t bios_device;
u8 biosemu_dev_init(struct device * device);
// NOTE: for dev_check_exprom to work, biosemu_dev_init MUST be called first!
u8 biosemu_dev_check_exprom(unsigned long rom_base_addr);
u8 biosemu_dev_translate_address(int type, unsigned long * addr);
/* endianness swap functions for 16 and 32 bit words
* copied from axon_pciconfig.c
*/
static inline void
out32le(void *addr, u32 val)
{
#if CONFIG_ARCH_X86 || CONFIG_ARCH_ARM
*((u32*) addr) = cpu_to_le32(val);
#else
asm volatile ("stwbrx %0, 0, %1"::"r" (val), "r"(addr));
#endif
}
static inline u32
in32le(void *addr)
{
u32 val;
#if CONFIG_ARCH_X86 || CONFIG_ARCH_ARM
val = cpu_to_le32(*((u32 *) addr));
#else
asm volatile ("lwbrx %0, 0, %1":"=r" (val):"r"(addr));
#endif
return val;
}
static inline void
out16le(void *addr, u16 val)
{
#if CONFIG_ARCH_X86 || CONFIG_ARCH_ARM
*((u16*) addr) = cpu_to_le16(val);
#else
asm volatile ("sthbrx %0, 0, %1"::"r" (val), "r"(addr));
#endif
}
static inline u16
in16le(void *addr)
{
u16 val;
#if CONFIG_ARCH_X86 || CONFIG_ARCH_ARM
val = cpu_to_le16(*((u16*) addr));
#else
asm volatile ("lhbrx %0, 0, %1":"=r" (val):"r"(addr));
#endif
return val;
}
/* debug function, dumps HID1 and HID4 to detect whether caches are on/off */
static inline void
dumpHID(void)
{
u64 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
|