blob: 37440a8051e85eca510e96c8902b4842ca2fbf49 [file] [log] [blame]
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00001/******************************************************************************
2 * Copyright (c) 2004, 2008 IBM Corporation
3 * Copyright (c) 2008, 2009 Pattrick Hueper <phueper@hueper.net>
Martin Rotha9e1a222016-01-14 14:15:24 -07004 *
Stefan Reinauer38cd29e2009-08-11 21:28:25 +00005 * All rights reserved.
Martin Rotha9e1a222016-01-14 14:15:24 -07006 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
9 * met:
10 *
11 * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 *
14 * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer
16 * in the documentation and/or other materials provided with the
17 * distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Stefan Reinauer38cd29e2009-08-11 21:28:25 +000030 *
31 * Contributors:
32 * IBM Corporation - initial implementation
33 *****************************************************************************/
34
35#ifndef DEVICE_LIB_H
36#define DEVICE_LIB_H
37
38#include <types.h>
Julius Werner9ff8f6f2015-02-23 14:31:09 -080039#include <endian.h>
Stefan Reinauer38cd29e2009-08-11 21:28:25 +000040#include "compat/of.h"
Stefan Reinauer38cd29e2009-08-11 21:28:25 +000041#include "debug.h"
42
Stefan Reinauer38cd29e2009-08-11 21:28:25 +000043// a Expansion Header Struct as defined in Plug and Play BIOS Spec 1.0a Chapter 3.2
44typedef struct {
45 char signature[4]; // signature
46 u8 structure_revision;
47 u8 length; // in 16 byte blocks
48 u16 next_header_offset; // offset to next Expansion Header as 16bit little-endian value, as offset from the start of the Expansion ROM
49 u8 reserved;
50 u8 checksum; // the sum of all bytes of the Expansion Header must be 0
51 u32 device_id; // PnP Device ID as 32bit little-endian value
52 u16 p_manufacturer_string; //16bit little-endian offset from start of Expansion ROM
53 u16 p_product_string; //16bit little-endian offset from start of Expansion ROM
54 u8 device_base_type;
55 u8 device_sub_type;
56 u8 device_if_type;
57 u8 device_indicators;
58 // the following vectors are all 16bit little-endian offsets from start of Expansion ROM
59 u16 bcv; // Boot Connection Vector
60 u16 dv; // Disconnect Vector
61 u16 bev; // Bootstrap Entry Vector
62 u16 reserved_2;
63 u16 sriv; // Static Resource Information Vector
Stefan Reinauer6a001132017-07-13 02:20:27 +020064} __packed exp_header_struct_t;
Stefan Reinauer38cd29e2009-08-11 21:28:25 +000065
66// a PCI Data Struct as defined in PCI 2.3 Spec Chapter 6.3.1.2
67typedef struct {
68 u8 signature[4]; // signature, the String "PCIR"
69 u16 vendor_id;
70 u16 device_id;
71 u16 reserved;
72 u16 pci_ds_length; // PCI Data Structure Length, 16bit little-endian value
73 u8 pci_ds_revision;
74 u8 class_code[3];
75 u16 img_length; // length of the Exp.ROM Image, 16bit little-endian value in 512 bytes
76 u16 img_revision;
77 u8 code_type;
78 u8 indicator;
79 u16 reserved_2;
Stefan Reinauer6a001132017-07-13 02:20:27 +020080} __packed pci_data_struct_t;
Stefan Reinauer38cd29e2009-08-11 21:28:25 +000081
82typedef struct {
83 u8 bus;
84 u8 devfn;
Julius Wernercd49cce2019-03-05 16:53:33 -080085#if CONFIG(PCI_OPTION_ROM_RUN_YABEL)
Stefan Reinauer38cd29e2009-08-11 21:28:25 +000086 struct device* dev;
Kyösti Mälkkif94aed82019-07-05 13:22:59 +030087 u64 puid; /* unused */
Stefan Reinauer38cd29e2009-08-11 21:28:25 +000088#else
Kyösti Mälkkif94aed82019-07-05 13:22:59 +030089 void *dev;
Stefan Reinauer38cd29e2009-08-11 21:28:25 +000090 u64 puid;
91 phandle_t phandle;
92 ihandle_t ihandle;
93#endif
94 // store the address of the BAR that is used to simulate
95 // legacy VGA memory accesses
96 u64 vmem_addr;
97 u64 vmem_size;
98 // used to buffer I/O Accesses, that do not access the I/O Range of the device...
99 // 64k might be overkill, but we can buffer all I/O accesses...
100 u8 io_buffer[64 * 1024];
101 u16 pci_vendor_id;
102 u16 pci_device_id;
103 // translated address of the "PC-Compatible" Expansion ROM Image for this device
104 unsigned long img_addr;
105 u32 img_size; // size of the Expansion ROM Image (read from the PCI Data Structure)
106} biosemu_device_t;
107
108typedef struct {
Julius Wernercd49cce2019-03-05 16:53:33 -0800109#if CONFIG(PCI_OPTION_ROM_RUN_YABEL)
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000110 unsigned long info;
111#else
112 u8 info;
113#endif
114 u8 bus;
115 u8 devfn;
116 u8 cfg_space_offset;
117 u64 address;
118 u64 address_offset;
119 u64 size;
Stefan Reinauer6a001132017-07-13 02:20:27 +0200120} __packed translate_address_t;
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000121
122// array to store address translations for this
123// device. Needed for faster address translation, so
124// not every I/O or Memory Access needs to call translate_address_dev
125// and access the device tree
Patrick Georgi91443042011-01-13 11:38:46 +0000126// 6 BARs, 1 Exp. ROM, 1 Cfg.Space, and 3 Legacy, plus 2 "special"
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000127// translations are supported... this should be enough for
128// most devices... for VGA it is enough anyways...
Patrick Georgi91443042011-01-13 11:38:46 +0000129extern translate_address_t translate_address_array[13];
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000130
131// index of last translate_address_array entry
132// set by get_dev_addr_info function
133extern u8 taa_last_entry;
134
Patrick Georgi91443042011-01-13 11:38:46 +0000135// add 1:1 mapped memory regions to translation table
136void biosemu_add_special_memory(u32 start, u32 size);
137
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000138/* the device we are working with... */
139extern biosemu_device_t bios_device;
140
141u8 biosemu_dev_init(struct device * device);
142// NOTE: for dev_check_exprom to work, biosemu_dev_init MUST be called first!
143u8 biosemu_dev_check_exprom(unsigned long rom_base_addr);
144
Patrick Georgi91443042011-01-13 11:38:46 +0000145u8 biosemu_dev_translate_address(int type, unsigned long * addr);
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000146
147/* endianness swap functions for 16 and 32 bit words
148 * copied from axon_pciconfig.c
149 */
150static inline void
151out32le(void *addr, u32 val)
152{
Kyösti Mälkki7336f972020-06-08 06:05:03 +0300153#if ENV_X86 || ENV_ARM || ENV_ARM64
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000154 *((u32*) addr) = cpu_to_le32(val);
155#else
156 asm volatile ("stwbrx %0, 0, %1"::"r" (val), "r"(addr));
157#endif
158}
159
160static inline u32
161in32le(void *addr)
162{
163 u32 val;
Kyösti Mälkki7336f972020-06-08 06:05:03 +0300164#if ENV_X86 || ENV_ARM || ENV_ARM64
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000165 val = cpu_to_le32(*((u32 *) addr));
166#else
167 asm volatile ("lwbrx %0, 0, %1":"=r" (val):"r"(addr));
168#endif
169 return val;
170}
171
172static inline void
173out16le(void *addr, u16 val)
174{
Kyösti Mälkki7336f972020-06-08 06:05:03 +0300175#if ENV_X86 || ENV_ARM || ENV_ARM64
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000176 *((u16*) addr) = cpu_to_le16(val);
177#else
178 asm volatile ("sthbrx %0, 0, %1"::"r" (val), "r"(addr));
179#endif
180}
181
182static inline u16
183in16le(void *addr)
184{
185 u16 val;
Kyösti Mälkki7336f972020-06-08 06:05:03 +0300186#if ENV_X86 || ENV_ARM || ENV_ARM64
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000187 val = cpu_to_le16(*((u16*) addr));
188#else
189 asm volatile ("lhbrx %0, 0, %1":"=r" (val):"r"(addr));
190#endif
191 return val;
192}
193
194/* debug function, dumps HID1 and HID4 to detect whether caches are on/off */
195static inline void
196dumpHID(void)
197{
198 u64 hid;
199 //HID1 = 1009
200 __asm__ __volatile__("mfspr %0, 1009":"=r"(hid));
Stefan Reinauer67a71ea2015-10-21 13:05:32 -0700201 printf("HID1: %016llx\n", (unsigned long long)hid);
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000202 //HID4 = 1012
203 __asm__ __volatile__("mfspr %0, 1012":"=r"(hid));
Stefan Reinauer67a71ea2015-10-21 13:05:32 -0700204 printf("HID4: %016llx\n", (unsigned long long)hid);
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000205}
206
207#endif