VirtualBox

source: vbox/trunk/src/VBox/Devices/PC/BIOS/pciutil.c

Last change on this file was 98103, checked in by vboxsync, 16 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.3 KB
Line 
1/* $Id: pciutil.c 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * Utility routines for calling the PCI BIOS.
4 */
5
6/*
7 * Copyright (C) 2011-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28#include <stdint.h>
29#include <string.h>
30#include "biosint.h"
31#include "inlines.h"
32
33/** PCI BIOS functions. */
34#define PCIBIOS_ID 0xb1
35#define PCIBIOS_PCI_BIOS_PRESENT 0x01
36#define PCIBIOS_FIND_PCI_DEVICE 0x02
37#define PCIBIOS_FIND_CLASS_CODE 0x03
38#define PCIBIOS_GENERATE_SPECIAL_CYCLE 0x06
39#define PCIBIOS_READ_CONFIG_BYTE 0x08
40#define PCIBIOS_READ_CONFIG_WORD 0x09
41#define PCIBIOS_READ_CONFIG_DWORD 0x0a
42#define PCIBIOS_WRITE_CONFIG_BYTE 0x0b
43#define PCIBIOS_WRITE_CONFIG_WORD 0x0c
44#define PCIBIOS_WRITE_CONFIG_DWORD 0x0d
45#define PCIBIOS_GET_IRQ_ROUTING_OPTIONS 0x0e
46#define PCIBIOS_SET_PCI_IRQ 0x0f
47
48/** Status codes. */
49#define SUCCESSFUL 0x00
50#define FUNC_NOT_SUPPORTED 0x81
51#define BAD_VENDOR_ID 0x83
52#define DEVICE_NOT_FOUND 0x86
53#define BAD_REGISTER_NUMBER 0x87
54#define SET_FAILED 0x88
55#define BUFFER_TOO_SMALL 0x89
56
57
58#if VBOX_BIOS_CPU >= 80386
59/* Warning: Destroys high bits of ECX. */
60uint16_t pci_find_class(uint16_t op, uint32_t dev_class, uint16_t index);
61# pragma aux pci_find_class = \
62 ".386" \
63 "shl ecx, 16" \
64 "mov cx, dx" \
65 "int 0x1a" \
66 "cmp ah, 0" \
67 "je found" \
68 "mov bx, 0xffff" \
69 "found:" \
70 parm [ax] [cx dx] [si] value [bx];
71#endif
72
73uint16_t pci_find_dev(uint16_t op, uint16_t dev_id, uint16_t ven_id, uint16_t index);
74#pragma aux pci_find_dev = \
75 "int 0x1a" \
76 "cmp ah, 0" \
77 "je found" \
78 "mov bx, 0xffff" \
79 "found:" \
80 parm [ax] [cx] [dx] [si] value [bx];
81
82uint8_t pci_read_cfgb(uint16_t op, uint16_t bus_dev_fn, uint16_t reg);
83#pragma aux pci_read_cfgb = \
84 "int 0x1a" \
85 parm [ax] [bx] [di] value [cl];
86
87uint16_t pci_read_cfgw(uint16_t op, uint16_t bus_dev_fn, uint16_t reg);
88#pragma aux pci_read_cfgw = \
89 "int 0x1a" \
90 parm [ax] [bx] [di] value [cx];
91
92#if VBOX_BIOS_CPU >= 80386
93/* Warning: Destroys high bits of ECX. */
94uint32_t pci_read_cfgd(uint16_t op, uint16_t bus_dev_fn, uint16_t reg);
95# pragma aux pci_read_cfgd = \
96 ".386" \
97 "int 0x1a" \
98 "mov ax, cx" \
99 "shr ecx, 16" \
100 parm [ax] [bx] [di] value [cx ax];
101#endif
102
103uint8_t pci_write_cfgb(uint16_t op, uint16_t bus_dev_fn, uint16_t reg, uint8_t val);
104#pragma aux pci_write_cfgb = \
105 "int 0x1a" \
106 parm [ax] [bx] [di] [cl];
107
108uint8_t pci_write_cfgw(uint16_t op, uint16_t bus_dev_fn, uint16_t reg, uint16_t val);
109#pragma aux pci_write_cfgw = \
110 "int 0x1a" \
111 parm [ax] [bx] [di] [cx];
112
113#if VBOX_BIOS_CPU >= 80386
114/* Warning: Destroys high bits of ECX. */
115uint8_t pci_write_cfgd(uint16_t op, uint16_t bus_dev_fn, uint16_t reg, uint32_t val);
116# pragma aux pci_write_cfgd = \
117 ".386" \
118 "shl ecx, 16" \
119 "mov cx, dx" \
120 "int 0x1a" \
121 parm [ax] [bx] [di] [cx dx];
122#endif
123
124
125/**
126 * Returns the bus/device/function of a PCI device with
127 * the given class code.
128 *
129 * @returns bus/device/fn in a 16-bit integer where
130 * where the upper byte contains the bus number
131 * and lower one the device and function number.
132 * 0xffff if no device was found.
133 * @param dev_class The PCI class code to search for.
134 */
135uint16_t pci_find_classcode(uint32_t dev_class)
136{
137#if VBOX_BIOS_CPU >= 80386
138 return pci_find_class((PCIBIOS_ID << 8) | PCIBIOS_FIND_CLASS_CODE, dev_class, 0);
139#else
140 return UINT16_C(0xffff);
141#endif
142}
143
144/**
145 * Returns the bus/device/function of a PCI device with
146 * the given base and sub-class code, ignoring the programming interface
147 * code.
148 *
149 * @returns bus/device/fn in a 16-bit integer where
150 * where the upper byte contains the bus number
151 * and lower one the device and function number.
152 * 0xffff if no device was found.
153 * @param dev_class The PCI class code to search for.
154 */
155uint16_t pci_find_class_noif(uint16_t dev_class)
156{
157#if VBOX_BIOS_CPU >= 80386
158 /* Internal call, not an interrupt service! */
159 return pci16_find_device(dev_class, 0 /*index*/, 1 /*search class*/, 1 /*ignore prog if*/);
160#else
161 return UINT16_C(0xffff);
162#endif
163}
164
165/**
166 * Returns the bus/device/function of a PCI device with
167 * the given vendor and device id.
168 *
169 * @returns bus/device/fn in one 16bit integer where
170 * where the upper byte contains the bus number
171 * and lower one the device and function number.
172 * 0xffff if no device was found.
173 * @param v_id The vendor ID.
174 * @param d_id The device ID.
175 */
176uint16_t pci_find_device(uint16_t v_id, uint16_t d_id)
177{
178 return pci_find_dev((PCIBIOS_ID << 8) | PCIBIOS_FIND_PCI_DEVICE, d_id, v_id, 0);
179}
180
181uint32_t pci_read_config_byte(uint8_t bus, uint8_t dev_fn, uint8_t reg)
182{
183 return pci_read_cfgb((PCIBIOS_ID << 8) | PCIBIOS_READ_CONFIG_BYTE, (bus << 8) | dev_fn, reg);
184}
185
186uint32_t pci_read_config_word(uint8_t bus, uint8_t dev_fn, uint8_t reg)
187{
188 return pci_read_cfgw((PCIBIOS_ID << 8) | PCIBIOS_READ_CONFIG_WORD, (bus << 8) | dev_fn, reg);
189}
190
191uint32_t pci_read_config_dword(uint8_t bus, uint8_t dev_fn, uint8_t reg)
192{
193#if VBOX_BIOS_CPU >= 80386
194 return pci_read_cfgd((PCIBIOS_ID << 8) | PCIBIOS_READ_CONFIG_DWORD, (bus << 8) | dev_fn, reg);
195#else
196 return pci_read_cfgw((PCIBIOS_ID << 8) | PCIBIOS_READ_CONFIG_WORD, (bus << 8) | dev_fn, reg)
197 || ((uint32_t)pci_read_cfgw((PCIBIOS_ID << 8) | PCIBIOS_READ_CONFIG_WORD, (bus << 8) | dev_fn, reg + 2) << 16);
198#endif
199}
200
201void pci_write_config_word(uint8_t bus, uint8_t dev_fn, uint8_t reg, uint16_t val)
202{
203 pci_write_cfgw((PCIBIOS_ID << 8) | PCIBIOS_WRITE_CONFIG_WORD, (bus << 8) | dev_fn, reg, val);
204}
205
206void pci_write_config_byte(uint8_t bus, uint8_t dev_fn, uint8_t reg, uint8_t val)
207{
208 pci_write_cfgb((PCIBIOS_ID << 8) | PCIBIOS_WRITE_CONFIG_BYTE, (bus << 8) | dev_fn, reg, val);
209}
210
211void pci_write_config_dword(uint8_t bus, uint8_t dev_fn, uint8_t reg, uint32_t val)
212{
213#if VBOX_BIOS_CPU >= 80386
214 pci_write_cfgd((PCIBIOS_ID << 8) | PCIBIOS_WRITE_CONFIG_DWORD, (bus << 8) | dev_fn, reg, val);
215#else
216 pci_write_cfgw((PCIBIOS_ID << 8) | PCIBIOS_WRITE_CONFIG_WORD, (bus << 8) | dev_fn, reg, val & 0xffff);
217 pci_write_cfgw((PCIBIOS_ID << 8) | PCIBIOS_WRITE_CONFIG_WORD, (bus << 8) | dev_fn, reg + 2, val >> 16);
218#endif
219}
220
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use