blob: b8891eec2d78fb9a3f493ae99c6d30c3736f2a09 [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>
4 * All rights reserved.
5 * This program and the accompanying materials
6 * are made available under the terms of the BSD License
7 * which accompanies this distribution, and is available at
8 * http://www.opensource.org/licenses/bsd-license.php
9 *
10 * Contributors:
11 * IBM Corporation - initial implementation
12 *****************************************************************************/
13
14#ifndef DEVICE_LIB_H
15#define DEVICE_LIB_H
16
17#include <types.h>
Julius Werner9ff8f6f2015-02-23 14:31:09 -080018#include <endian.h>
Stefan Reinauer38cd29e2009-08-11 21:28:25 +000019#include "compat/of.h"
Stefan Reinauer38cd29e2009-08-11 21:28:25 +000020#include "debug.h"
21
22
23// a Expansion Header Struct as defined in Plug and Play BIOS Spec 1.0a Chapter 3.2
24typedef struct {
25 char signature[4]; // signature
26 u8 structure_revision;
27 u8 length; // in 16 byte blocks
28 u16 next_header_offset; // offset to next Expansion Header as 16bit little-endian value, as offset from the start of the Expansion ROM
29 u8 reserved;
30 u8 checksum; // the sum of all bytes of the Expansion Header must be 0
31 u32 device_id; // PnP Device ID as 32bit little-endian value
32 u16 p_manufacturer_string; //16bit little-endian offset from start of Expansion ROM
33 u16 p_product_string; //16bit little-endian offset from start of Expansion ROM
34 u8 device_base_type;
35 u8 device_sub_type;
36 u8 device_if_type;
37 u8 device_indicators;
38 // the following vectors are all 16bit little-endian offsets from start of Expansion ROM
39 u16 bcv; // Boot Connection Vector
40 u16 dv; // Disconnect Vector
41 u16 bev; // Bootstrap Entry Vector
42 u16 reserved_2;
43 u16 sriv; // Static Resource Information Vector
44} __attribute__ ((__packed__)) exp_header_struct_t;
45
46// a PCI Data Struct as defined in PCI 2.3 Spec Chapter 6.3.1.2
47typedef struct {
48 u8 signature[4]; // signature, the String "PCIR"
49 u16 vendor_id;
50 u16 device_id;
51 u16 reserved;
52 u16 pci_ds_length; // PCI Data Structure Length, 16bit little-endian value
53 u8 pci_ds_revision;
54 u8 class_code[3];
55 u16 img_length; // length of the Exp.ROM Image, 16bit little-endian value in 512 bytes
56 u16 img_revision;
57 u8 code_type;
58 u8 indicator;
59 u16 reserved_2;
60} __attribute__ ((__packed__)) pci_data_struct_t;
61
62typedef struct {
63 u8 bus;
64 u8 devfn;
Stefan Reinauer21f81932015-10-21 13:04:34 -070065#if IS_ENABLED(CONFIG_PCI_OPTION_ROM_RUN_YABEL)
Stefan Reinauer38cd29e2009-08-11 21:28:25 +000066 struct device* dev;
67#else
68 u64 puid;
69 phandle_t phandle;
70 ihandle_t ihandle;
71#endif
72 // store the address of the BAR that is used to simulate
73 // legacy VGA memory accesses
74 u64 vmem_addr;
75 u64 vmem_size;
76 // used to buffer I/O Accesses, that do not access the I/O Range of the device...
77 // 64k might be overkill, but we can buffer all I/O accesses...
78 u8 io_buffer[64 * 1024];
79 u16 pci_vendor_id;
80 u16 pci_device_id;
81 // translated address of the "PC-Compatible" Expansion ROM Image for this device
82 unsigned long img_addr;
83 u32 img_size; // size of the Expansion ROM Image (read from the PCI Data Structure)
84} biosemu_device_t;
85
86typedef struct {
Stefan Reinauerd4814bd2011-04-21 20:45:45 +000087#if CONFIG_PCI_OPTION_ROM_RUN_YABEL
Stefan Reinauer38cd29e2009-08-11 21:28:25 +000088 unsigned long info;
89#else
90 u8 info;
91#endif
92 u8 bus;
93 u8 devfn;
94 u8 cfg_space_offset;
95 u64 address;
96 u64 address_offset;
97 u64 size;
98} __attribute__ ((__packed__)) translate_address_t;
99
100// array to store address translations for this
101// device. Needed for faster address translation, so
102// not every I/O or Memory Access needs to call translate_address_dev
103// and access the device tree
Patrick Georgi91443042011-01-13 11:38:46 +0000104// 6 BARs, 1 Exp. ROM, 1 Cfg.Space, and 3 Legacy, plus 2 "special"
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000105// translations are supported... this should be enough for
106// most devices... for VGA it is enough anyways...
Patrick Georgi91443042011-01-13 11:38:46 +0000107extern translate_address_t translate_address_array[13];
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000108
109// index of last translate_address_array entry
110// set by get_dev_addr_info function
111extern u8 taa_last_entry;
112
Patrick Georgi91443042011-01-13 11:38:46 +0000113// add 1:1 mapped memory regions to translation table
114void biosemu_add_special_memory(u32 start, u32 size);
115
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000116/* the device we are working with... */
117extern biosemu_device_t bios_device;
118
119u8 biosemu_dev_init(struct device * device);
120// NOTE: for dev_check_exprom to work, biosemu_dev_init MUST be called first!
121u8 biosemu_dev_check_exprom(unsigned long rom_base_addr);
122
Patrick Georgi91443042011-01-13 11:38:46 +0000123u8 biosemu_dev_translate_address(int type, unsigned long * addr);
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000124
125/* endianness swap functions for 16 and 32 bit words
126 * copied from axon_pciconfig.c
127 */
128static inline void
129out32le(void *addr, u32 val)
130{
Gabe Black51edd542013-09-30 23:00:33 -0700131#if CONFIG_ARCH_X86 || CONFIG_ARCH_ARM
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000132 *((u32*) addr) = cpu_to_le32(val);
133#else
134 asm volatile ("stwbrx %0, 0, %1"::"r" (val), "r"(addr));
135#endif
136}
137
138static inline u32
139in32le(void *addr)
140{
141 u32 val;
Gabe Black51edd542013-09-30 23:00:33 -0700142#if CONFIG_ARCH_X86 || CONFIG_ARCH_ARM
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000143 val = cpu_to_le32(*((u32 *) addr));
144#else
145 asm volatile ("lwbrx %0, 0, %1":"=r" (val):"r"(addr));
146#endif
147 return val;
148}
149
150static inline void
151out16le(void *addr, u16 val)
152{
Gabe Black51edd542013-09-30 23:00:33 -0700153#if CONFIG_ARCH_X86 || CONFIG_ARCH_ARM
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000154 *((u16*) addr) = cpu_to_le16(val);
155#else
156 asm volatile ("sthbrx %0, 0, %1"::"r" (val), "r"(addr));
157#endif
158}
159
160static inline u16
161in16le(void *addr)
162{
163 u16 val;
Gabe Black51edd542013-09-30 23:00:33 -0700164#if CONFIG_ARCH_X86 || CONFIG_ARCH_ARM
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000165 val = cpu_to_le16(*((u16*) addr));
166#else
167 asm volatile ("lhbrx %0, 0, %1":"=r" (val):"r"(addr));
168#endif
169 return val;
170}
171
172/* debug function, dumps HID1 and HID4 to detect whether caches are on/off */
173static inline void
174dumpHID(void)
175{
176 u64 hid;
177 //HID1 = 1009
178 __asm__ __volatile__("mfspr %0, 1009":"=r"(hid));
Stefan Reinauer67a71ea2015-10-21 13:05:32 -0700179 printf("HID1: %016llx\n", (unsigned long long)hid);
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000180 //HID4 = 1012
181 __asm__ __volatile__("mfspr %0, 1012":"=r"(hid));
Stefan Reinauer67a71ea2015-10-21 13:05:32 -0700182 printf("HID4: %016llx\n", (unsigned long long)hid);
Stefan Reinauer38cd29e2009-08-11 21:28:25 +0000183}
184
185#endif