VirtualBox

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

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette