VirtualBox

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

Last change on this file since 78374 was 78052, checked in by vboxsync, 6 years ago

BIOS: Only probe IDE devices if a PCI IDE controller is present (see bugref:6549).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 6.9 KB
Line 
1/* $Id: pciutil.c 78052 2019-04-09 10:13:30Z vboxsync $ */
2/** @file
3 * Utility routines for calling the PCI BIOS.
4 */
5
6/*
7 * Copyright (C) 2011-2019 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 "xchg cx, dx" \
109 "shl ecx, 16" \
110 "mov cx, dx" \
111 "int 0x1a" \
112 parm [ax] [bx] [di] [dx cx];
113#endif
114
115
116/**
117 * Returns the bus/device/function of a PCI device with
118 * the given class code.
119 *
120 * @returns bus/device/fn in a 16-bit integer where
121 * where the upper byte contains the bus number
122 * and lower one the device and function number.
123 * 0xffff if no device was found.
124 * @param dev_class The PCI class code to search for.
125 */
126uint16_t pci_find_classcode(uint32_t dev_class)
127{
128#if VBOX_BIOS_CPU >= 80386
129 return pci_find_class((PCIBIOS_ID << 8) | PCIBIOS_FIND_CLASS_CODE, dev_class, 0);
130#else
131 return UINT16_C(0xffff);
132#endif
133}
134
135/**
136 * Returns the bus/device/function of a PCI device with
137 * the given base and sub-class code, ignoring the programming interface
138 * code.
139 *
140 * @returns bus/device/fn in a 16-bit integer where
141 * where the upper byte contains the bus number
142 * and lower one the device and function number.
143 * 0xffff if no device was found.
144 * @param dev_class The PCI class code to search for.
145 */
146uint16_t pci_find_class_noif(uint16_t dev_class)
147{
148#if VBOX_BIOS_CPU >= 80386
149 /* Internal call, not an interrupt service! */
150 return pci16_find_device(dev_class, 0 /*index*/, 1 /*search class*/, 1 /*ignore prog if*/);
151#else
152 return UINT16_C(0xffff);
153#endif
154}
155
156/**
157 * Returns the bus/device/function of a PCI device with
158 * the given vendor and device id.
159 *
160 * @returns bus/device/fn in one 16bit integer where
161 * where the upper byte contains the bus number
162 * and lower one the device and function number.
163 * 0xffff if no device was found.
164 * @param v_id The vendor ID.
165 * @param d_id The device ID.
166 */
167uint16_t pci_find_device(uint16_t v_id, uint16_t d_id)
168{
169 return pci_find_dev((PCIBIOS_ID << 8) | PCIBIOS_FIND_PCI_DEVICE, d_id, v_id, 0);
170}
171
172uint32_t pci_read_config_byte(uint8_t bus, uint8_t dev_fn, uint8_t reg)
173{
174 return pci_read_cfgb((PCIBIOS_ID << 8) | PCIBIOS_READ_CONFIG_BYTE, (bus << 8) | dev_fn, reg);
175}
176
177uint32_t pci_read_config_word(uint8_t bus, uint8_t dev_fn, uint8_t reg)
178{
179 return pci_read_cfgw((PCIBIOS_ID << 8) | PCIBIOS_READ_CONFIG_WORD, (bus << 8) | dev_fn, reg);
180}
181
182uint32_t pci_read_config_dword(uint8_t bus, uint8_t dev_fn, uint8_t reg)
183{
184#if VBOX_BIOS_CPU >= 80386
185 return pci_read_cfgd((PCIBIOS_ID << 8) | PCIBIOS_READ_CONFIG_DWORD, (bus << 8) | dev_fn, reg);
186#else
187 return pci_read_cfgw((PCIBIOS_ID << 8) | PCIBIOS_READ_CONFIG_WORD, (bus << 8) | dev_fn, reg)
188 || ((uint32_t)pci_read_cfgw((PCIBIOS_ID << 8) | PCIBIOS_READ_CONFIG_WORD, (bus << 8) | dev_fn, reg + 2) << 16);
189#endif
190}
191
192void pci_write_config_word(uint8_t bus, uint8_t dev_fn, uint8_t reg, uint16_t val)
193{
194 pci_write_cfgw((PCIBIOS_ID << 8) | PCIBIOS_WRITE_CONFIG_WORD, (bus << 8) | dev_fn, reg, val);
195}
196
197#if 0 /* Disabled to save space because they are not needed. Might become useful in the future. */
198void pci_write_config_byte(uint8_t bus, uint8_t dev_fn, uint8_t reg, uint8_t val)
199{
200 pci_write_cfgb((PCIBIOS_ID << 8) | PCIBIOS_WRITE_CONFIG_BYTE, (bus << 8) | dev_fn, reg, val);
201}
202
203void pci_write_config_dword(uint8_t bus, uint8_t dev_fn, uint8_t reg, uint32_t val)
204{
205 pci_write_cfgd((PCIBIOS_ID << 8) | PCIBIOS_WRITE_CONFIG_DWORD, (bus << 8) | dev_fn, reg, val);
206}
207#endif /* 0 */
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