VirtualBox

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

Last change on this file since 60433 was 60433, checked in by vboxsync, 9 years ago

PCBIOS: 286 fixes, improved the BIOSORG checking as overflows in this area are hard to figure out.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 6.3 KB
Line 
1/** @file
2 * Utility routines for calling the PCI BIOS.
3 */
4
5/*
6 * Copyright (C) 2011-2015 Oracle Corporation
7 *
8 * This file is part of VirtualBox Open Source Edition (OSE), as
9 * available from http://www.virtualbox.org. This file is free software;
10 * you can redistribute it and/or modify it under the terms of the GNU
11 * General Public License (GPL) as published by the Free Software
12 * Foundation, in version 2 as it comes in the "COPYING" file of the
13 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
14 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
15 */
16
17#include <stdint.h>
18#include <string.h>
19#include "biosint.h"
20#include "inlines.h"
21
22/** PCI BIOS functions. */
23#define PCIBIOS_ID 0xb1
24#define PCIBIOS_PCI_BIOS_PRESENT 0x01
25#define PCIBIOS_FIND_PCI_DEVICE 0x02
26#define PCIBIOS_FIND_CLASS_CODE 0x03
27#define PCIBIOS_GENERATE_SPECIAL_CYCLE 0x06
28#define PCIBIOS_READ_CONFIG_BYTE 0x08
29#define PCIBIOS_READ_CONFIG_WORD 0x09
30#define PCIBIOS_READ_CONFIG_DWORD 0x0a
31#define PCIBIOS_WRITE_CONFIG_BYTE 0x0b
32#define PCIBIOS_WRITE_CONFIG_WORD 0x0c
33#define PCIBIOS_WRITE_CONFIG_DWORD 0x0d
34#define PCIBIOS_GET_IRQ_ROUTING_OPTIONS 0x0e
35#define PCIBIOS_SET_PCI_IRQ 0x0f
36
37/** Status codes. */
38#define SUCCESSFUL 0x00
39#define FUNC_NOT_SUPPORTED 0x81
40#define BAD_VENDOR_ID 0x83
41#define DEVICE_NOT_FOUND 0x86
42#define BAD_REGISTER_NUMBER 0x87
43#define SET_FAILED 0x88
44#define BUFFER_TOO_SMALL 0x89
45
46
47#if VBOX_BIOS_CPU >= 80386
48/* Warning: Destroys high bits of ECX. */
49uint16_t pci_find_class(uint16_t op, uint32_t dev_class, uint16_t start_bdf);
50# pragma aux pci_find_class = \
51 ".386" \
52 "shl ecx, 16" \
53 "mov cx, dx" \
54 "int 0x1a" \
55 "cmp ah, 0" \
56 "je found" \
57 "mov bx, 0xffff" \
58 "found:" \
59 parm [ax] [cx dx] [si] value [bx];
60#endif
61
62uint16_t pci_find_dev(uint16_t op, uint16_t dev_id, uint16_t ven_id, uint16_t start_bdf);
63#pragma aux pci_find_dev = \
64 "int 0x1a" \
65 "cmp ah, 0" \
66 "je found" \
67 "mov bx, 0xffff" \
68 "found:" \
69 parm [ax] [cx] [dx] [si] value [bx];
70
71uint8_t pci_read_cfgb(uint16_t op, uint16_t bus_dev_fn, uint16_t reg);
72#pragma aux pci_read_cfgb = \
73 "int 0x1a" \
74 parm [ax] [bx] [di] value [cl];
75
76uint16_t pci_read_cfgw(uint16_t op, uint16_t bus_dev_fn, uint16_t reg);
77#pragma aux pci_read_cfgw = \
78 "int 0x1a" \
79 parm [ax] [bx] [di] value [cx];
80
81#if VBOX_BIOS_CPU >= 80386
82/* Warning: Destroys high bits of ECX. */
83uint32_t pci_read_cfgd(uint16_t op, uint16_t bus_dev_fn, uint16_t reg);
84# pragma aux pci_read_cfgd = \
85 ".386" \
86 "int 0x1a" \
87 "mov ax, cx" \
88 "shr ecx, 16" \
89 parm [ax] [bx] [di] value [cx ax];
90#endif
91
92uint8_t pci_write_cfgb(uint16_t op, uint16_t bus_dev_fn, uint16_t reg, uint8_t val);
93#pragma aux pci_write_cfgb = \
94 "int 0x1a" \
95 parm [ax] [bx] [di] [cl];
96
97uint8_t pci_write_cfgw(uint16_t op, uint16_t bus_dev_fn, uint16_t reg, uint16_t val);
98#pragma aux pci_write_cfgw = \
99 "int 0x1a" \
100 parm [ax] [bx] [di] [cx];
101
102#if VBOX_BIOS_CPU >= 80386
103/* Warning: Destroys high bits of ECX. */
104uint8_t pci_write_cfgd(uint16_t op, uint16_t bus_dev_fn, uint16_t reg, uint32_t val);
105# pragma aux pci_write_cfgd = \
106 ".386" \
107 "xchg cx, dx" \
108 "shl ecx, 16" \
109 "mov cx, dx" \
110 "int 0x1a" \
111 parm [ax] [bx] [di] [dx cx];
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 * VBOX_AHCI_NO_DEVICE 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
134uint32_t pci_read_config_byte(uint8_t bus, uint8_t dev_fn, uint8_t reg)
135{
136 return pci_read_cfgb((PCIBIOS_ID << 8) | PCIBIOS_READ_CONFIG_BYTE, (bus << 8) | dev_fn, reg);
137}
138
139uint32_t pci_read_config_word(uint8_t bus, uint8_t dev_fn, uint8_t reg)
140{
141 return pci_read_cfgw((PCIBIOS_ID << 8) | PCIBIOS_READ_CONFIG_WORD, (bus << 8) | dev_fn, reg);
142}
143
144uint32_t pci_read_config_dword(uint8_t bus, uint8_t dev_fn, uint8_t reg)
145{
146#if VBOX_BIOS_CPU >= 80386
147 return pci_read_cfgd((PCIBIOS_ID << 8) | PCIBIOS_READ_CONFIG_DWORD, (bus << 8) | dev_fn, reg);
148#else
149 return pci_read_cfgw((PCIBIOS_ID << 8) | PCIBIOS_READ_CONFIG_WORD, (bus << 8) | dev_fn, reg)
150 || ((uint32_t)pci_read_cfgw((PCIBIOS_ID << 8) | PCIBIOS_READ_CONFIG_WORD, (bus << 8) | dev_fn, reg + 2) << 16);
151#endif
152}
153
154#if 0 /* Disabled to save space because they are not needed. Might become useful in the future. */
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 * VBOX_AHCI_NO_DEVICE if no device was found.
163 * @param u16Vendor The vendor ID.
164 * @param u16Device 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, v_id, d_id, 0);
169}
170
171void pci_write_config_byte(uint8_t bus, uint8_t dev_fn, uint8_t reg, uint8_t val)
172{
173 pci_write_cfgb((PCIBIOS_ID << 8) | PCIBIOS_WRITE_CONFIG_BYTE, (bus << 8) | dev_fn, reg, val);
174}
175
176void pci_write_config_word(uint8_t bus, uint8_t dev_fn, uint8_t reg, uint16_t val)
177{
178 pci_write_cfgw((PCIBIOS_ID << 8) | PCIBIOS_WRITE_CONFIG_WORD, (bus << 8) | dev_fn, reg, val);
179}
180
181void pci_write_config_dword(uint8_t bus, uint8_t dev_fn, uint8_t reg, uint32_t val)
182{
183 pci_write_cfgd((PCIBIOS_ID << 8) | PCIBIOS_WRITE_CONFIG_DWORD, (bus << 8) | dev_fn, reg, val);
184}
185#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