[69300] | 1 | ; $Id: pcibios.inc 98103 2023-01-17 14:15:46Z vboxsync $
|
---|
| 2 | ;; @file
|
---|
| 3 | ; ???
|
---|
| 4 | ;
|
---|
[38699] | 5 |
|
---|
[69300] | 6 | ;
|
---|
[98103] | 7 | ; Copyright (C) 2006-2023 Oracle and/or its affiliates.
|
---|
[69300] | 8 | ;
|
---|
[96407] | 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
|
---|
[69498] | 26 | ; --------------------------------------------------------------------
|
---|
[69300] | 27 | ;
|
---|
| 28 | ; This code is based on:
|
---|
| 29 | ;
|
---|
| 30 | ; ROM BIOS for use with Bochs/Plex86/QEMU emulation environment
|
---|
| 31 | ;
|
---|
| 32 | ; Copyright (C) 2002 MandrakeSoft S.A.
|
---|
| 33 | ;
|
---|
| 34 | ; MandrakeSoft S.A.
|
---|
| 35 | ; 43, rue d'Aboukir
|
---|
| 36 | ; 75002 Paris - France
|
---|
| 37 | ; http://www.linux-mandrake.com/
|
---|
| 38 | ; http://www.mandrakesoft.com/
|
---|
| 39 | ;
|
---|
| 40 | ; This library is free software; you can redistribute it and/or
|
---|
| 41 | ; modify it under the terms of the GNU Lesser General Public
|
---|
| 42 | ; License as published by the Free Software Foundation; either
|
---|
| 43 | ; version 2 of the License, or (at your option) any later version.
|
---|
| 44 | ;
|
---|
| 45 | ; This library is distributed in the hope that it will be useful,
|
---|
| 46 | ; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
| 47 | ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
---|
| 48 | ; Lesser General Public License for more details.
|
---|
| 49 | ;
|
---|
| 50 | ; You should have received a copy of the GNU Lesser General Public
|
---|
| 51 | ; License along with this library; if not, write to the Free Software
|
---|
| 52 | ; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
---|
| 53 | ;
|
---|
[43117] | 54 |
|
---|
| 55 | ; Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
|
---|
| 56 | ; other than GPL or LGPL is available it will apply instead, Oracle elects to use only
|
---|
| 57 | ; the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
|
---|
| 58 | ; a choice of LGPL license versions is made available with the language indicating
|
---|
| 59 | ; that LGPLv2 or any later version may be used, or where a choice of which version
|
---|
| 60 | ; of the LGPL is applied is otherwise unspecified.
|
---|
| 61 |
|
---|
[69300] | 62 |
|
---|
[38699] | 63 | include pcicfg.inc
|
---|
| 64 |
|
---|
| 65 | if BX_PCIBIOS
|
---|
| 66 |
|
---|
[38890] | 67 | ifdef DEBUG
|
---|
| 68 |
|
---|
| 69 | ; Publics for easier debugging and disassembly
|
---|
| 70 |
|
---|
| 71 | public pcibios_init_iomem_bases
|
---|
| 72 | public pci_init_io_loop1
|
---|
| 73 | public pci_init_io_loop2
|
---|
| 74 | public init_io_base
|
---|
| 75 | public next_pci_base
|
---|
| 76 | public enable_iomem_space
|
---|
| 77 | public next_pci_dev
|
---|
| 78 | public pcibios_init_set_elcr
|
---|
| 79 | public is_master_pic
|
---|
| 80 | public pcibios_init_irqs
|
---|
| 81 | public pci_init_irq_loop1
|
---|
| 82 | public pci_init_irq_loop2
|
---|
| 83 | public pci_test_int_pin
|
---|
| 84 | public pirq_found
|
---|
| 85 | public next_pci_func
|
---|
| 86 | public next_pir_entry
|
---|
| 87 | public pci_init_end
|
---|
| 88 |
|
---|
| 89 | endif
|
---|
| 90 |
|
---|
[38699] | 91 | .386
|
---|
| 92 |
|
---|
| 93 | if not BX_ROMBIOS32
|
---|
| 94 | pci_irq_list:
|
---|
[69300] | 95 | db 11, 10, 9, 11
|
---|
[38699] | 96 |
|
---|
| 97 | pcibios_init_sel_reg:
|
---|
| 98 | push eax
|
---|
| 99 | mov eax, 800000h
|
---|
| 100 | mov ax, bx
|
---|
| 101 | shl eax, 8
|
---|
| 102 | and dl, 0FCh
|
---|
| 103 | or al, dl
|
---|
| 104 | mov dx, PCI_CFG1
|
---|
| 105 | out dx, eax
|
---|
| 106 | pop eax
|
---|
| 107 | ret
|
---|
| 108 |
|
---|
| 109 | pcibios_init_iomem_bases:
|
---|
| 110 | push bp
|
---|
| 111 | mov bp, sp
|
---|
[67668] | 112 | ifdef VBOX
|
---|
[69300] | 113 | mov eax,19200509
|
---|
[67668] | 114 | mov dx,410h
|
---|
| 115 | out dx, eax
|
---|
| 116 | else
|
---|
| 117 | ; This incomplete PCI resource setup code is less functional than the PCI
|
---|
| 118 | ; resource assignment created by the fake PCI BIOS and is therefore disabled.
|
---|
| 119 | ; Blindly enabling everything on the root bus (including bus mastering!) can
|
---|
| 120 | ; only be called buggy. It causes the trouble with AMD PCNet which it then
|
---|
| 121 | ; tries to work around, but that still contains a race.
|
---|
[38699] | 122 | mov eax, 0E0000000h ; base for memory init
|
---|
| 123 | push eax
|
---|
[38890] | 124 | mov ax, 0D000h ; base for i/o init
|
---|
[38699] | 125 | push ax
|
---|
| 126 | mov ax, 010h ; start at base address #0
|
---|
| 127 | push ax
|
---|
| 128 | mov bx, 8
|
---|
| 129 | pci_init_io_loop1:
|
---|
| 130 | mov dl, 0
|
---|
| 131 | call pcibios_init_sel_reg
|
---|
| 132 | mov dx, PCI_CFG2
|
---|
| 133 | in ax, dx
|
---|
| 134 | cmp ax, 0FFFFh
|
---|
| 135 | jz next_pci_dev
|
---|
| 136 |
|
---|
[67668] | 137 | ifndef VBOX ; This currently breaks restoring a previously saved state.
|
---|
[38699] | 138 | mov dl, 4 ; disable i/o and memory space access
|
---|
| 139 | call pcibios_init_sel_reg
|
---|
| 140 | mov dx, PCI_CFG2
|
---|
| 141 | in al, dx
|
---|
| 142 | and al, 0FCh
|
---|
| 143 | out dx, al
|
---|
| 144 | pci_init_io_loop2:
|
---|
| 145 | mov dl, [bp-8]
|
---|
| 146 | call pcibios_init_sel_reg
|
---|
| 147 | mov dx, PCI_CFG2
|
---|
| 148 | in eax, dx
|
---|
| 149 | test al, 1
|
---|
| 150 | jnz init_io_base
|
---|
| 151 |
|
---|
| 152 | mov ecx, eax
|
---|
| 153 | mov eax, 0FFFFFFFFh
|
---|
| 154 | out dx, eax
|
---|
| 155 | in eax, dx
|
---|
| 156 | cmp eax, ecx
|
---|
| 157 | je next_pci_base
|
---|
| 158 | xor eax, 0FFFFFFFFh
|
---|
| 159 | mov ecx, eax
|
---|
| 160 | mov eax, [bp-4]
|
---|
| 161 | out dx, eax
|
---|
| 162 | add eax, ecx ; calculate next free mem base
|
---|
| 163 | add eax, 01000000h
|
---|
| 164 | and eax, 0FF000000h
|
---|
| 165 | mov [bp-4], eax
|
---|
| 166 | jmp next_pci_base
|
---|
| 167 |
|
---|
| 168 | init_io_base:
|
---|
| 169 | mov cx, ax
|
---|
| 170 | mov ax, 0FFFFh
|
---|
[38890] | 171 | out dx, eax
|
---|
| 172 | in eax, dx
|
---|
[38699] | 173 | cmp ax, cx
|
---|
| 174 | je next_pci_base
|
---|
| 175 |
|
---|
| 176 | xor ax, 0FFFEh
|
---|
| 177 | mov cx, ax
|
---|
| 178 | mov ax, [bp-6]
|
---|
[38890] | 179 | out dx, eax
|
---|
[38699] | 180 | add ax, cx ; calculate next free i/o base
|
---|
| 181 | add ax, 00100h
|
---|
| 182 | and ax, 0FF00h
|
---|
| 183 | mov [bp-6], ax
|
---|
| 184 | next_pci_base:
|
---|
| 185 | mov al, [bp-8]
|
---|
| 186 | add al, 4
|
---|
| 187 | cmp al, 28h
|
---|
| 188 | je enable_iomem_space
|
---|
| 189 |
|
---|
| 190 | mov byte ptr[bp-8], al
|
---|
| 191 | jmp pci_init_io_loop2
|
---|
[39589] | 192 | endif ; !VBOX
|
---|
[38699] | 193 |
|
---|
| 194 | enable_iomem_space:
|
---|
| 195 | mov dl, 4 ;; enable i/o and memory space access if available
|
---|
| 196 | call pcibios_init_sel_reg
|
---|
| 197 | mov dx, PCI_CFG2
|
---|
| 198 | in al, dx
|
---|
| 199 | or al, 7
|
---|
| 200 | out dx, al
|
---|
| 201 | ifdef VBOX
|
---|
| 202 | mov dl, 0 ; check if PCI device is AMD PCNet
|
---|
| 203 | call pcibios_init_sel_reg
|
---|
| 204 | mov dx, PCI_CFG2
|
---|
| 205 | in eax, dx
|
---|
| 206 | cmp eax, 020001022h
|
---|
| 207 | jne next_pci_dev
|
---|
| 208 |
|
---|
| 209 | mov dl, 10h ; get I/O address
|
---|
| 210 | call pcibios_init_sel_reg
|
---|
| 211 | mov dx, PCI_CFG2
|
---|
| 212 | in ax, dx
|
---|
| 213 | and ax, 0FFFCh
|
---|
| 214 | mov cx, ax
|
---|
| 215 | mov dx, cx
|
---|
| 216 | add dx, 14h ; reset register if PCNet is in word I/O mode
|
---|
| 217 | in ax, dx ; reset is performed by reading the reset register
|
---|
| 218 | mov dx, cx
|
---|
| 219 | add dx, 18h ; reset register if PCNet is in word I/O mode
|
---|
| 220 | in eax, dx ; reset is performed by reading the reset register
|
---|
[69300] | 221 | endif ; VBOX
|
---|
[38699] | 222 | next_pci_dev:
|
---|
| 223 | mov byte ptr[bp-8], 10h
|
---|
| 224 | inc bx
|
---|
| 225 | cmp bx, 0100h
|
---|
| 226 | jne pci_init_io_loop1
|
---|
[67668] | 227 | endif ; !VBOX
|
---|
[38699] | 228 | mov sp, bp
|
---|
| 229 | pop bp
|
---|
| 230 | ret
|
---|
| 231 |
|
---|
| 232 | pcibios_init_set_elcr:
|
---|
| 233 | push ax
|
---|
| 234 | push cx
|
---|
| 235 | mov dx, 04D0h
|
---|
| 236 | test al, 8
|
---|
| 237 | jz is_master_pic
|
---|
| 238 |
|
---|
| 239 | inc dx
|
---|
| 240 | and al, 7
|
---|
| 241 | is_master_pic:
|
---|
| 242 | mov cl, al
|
---|
| 243 | mov bl, 1
|
---|
| 244 | shl bl, cl
|
---|
| 245 | in al, dx
|
---|
| 246 | or al, bl
|
---|
| 247 | out dx, al
|
---|
| 248 | pop cx
|
---|
| 249 | pop ax
|
---|
| 250 | ret
|
---|
| 251 |
|
---|
| 252 | pcibios_init_irqs:
|
---|
| 253 | push ds
|
---|
| 254 | push bp
|
---|
| 255 | mov ax, 0F000h
|
---|
| 256 | mov ds, ax
|
---|
[67668] | 257 | ifndef VBOX
|
---|
| 258 | ; this code works OK, but it's unnecessary effort since the fake PCI BIOS
|
---|
| 259 | ; already configured the IRQ lines and the ELCR correctly
|
---|
[38699] | 260 | mov dx, 04D0h ;; reset ELCR1 + ELCR2
|
---|
| 261 | mov al, 0
|
---|
| 262 | out dx, al
|
---|
| 263 | inc dx
|
---|
| 264 | out dx, al
|
---|
| 265 | mov si, pci_routing_table_structure
|
---|
| 266 | mov bh, [si+8]
|
---|
| 267 | mov bl, [si+9]
|
---|
| 268 | mov dl, 0
|
---|
| 269 | call pcibios_init_sel_reg
|
---|
| 270 | mov dx, PCI_CFG2
|
---|
| 271 | in eax, dx
|
---|
| 272 | cmp eax, [si+12] ;; check irq router
|
---|
| 273 | jne pci_init_end
|
---|
| 274 |
|
---|
| 275 | mov dl, [si+34]
|
---|
| 276 | call pcibios_init_sel_reg
|
---|
| 277 | push bx ;; save irq router bus + devfunc
|
---|
| 278 | mov dx, PCI_CFG2
|
---|
| 279 | mov ax, 8080h
|
---|
| 280 | out dx, ax ;; reset PIRQ route control
|
---|
| 281 | add dx, 2
|
---|
| 282 | out dx, ax
|
---|
| 283 | mov ax, [si+6]
|
---|
| 284 | sub ax, 20h
|
---|
| 285 | shr ax, 4
|
---|
| 286 | mov cx, ax
|
---|
| 287 | add si, 20h ;; set pointer to 1st entry
|
---|
| 288 | mov bp, sp
|
---|
| 289 | mov ax, pci_irq_list
|
---|
| 290 | push ax
|
---|
| 291 | xor ax, ax
|
---|
| 292 | push ax
|
---|
| 293 | pci_init_irq_loop1:
|
---|
| 294 | mov bh, [si]
|
---|
| 295 | mov bl, [si+1]
|
---|
| 296 | pci_init_irq_loop2:
|
---|
| 297 | mov dl, 0
|
---|
| 298 | call pcibios_init_sel_reg
|
---|
| 299 | mov dx, PCI_CFG2
|
---|
| 300 | in ax, dx
|
---|
| 301 | cmp ax, 0FFFFh
|
---|
| 302 | jnz pci_test_int_pin
|
---|
| 303 |
|
---|
| 304 | test bl, 7
|
---|
| 305 | jz next_pir_entry
|
---|
| 306 |
|
---|
| 307 | jmp next_pci_func
|
---|
| 308 |
|
---|
| 309 | pci_test_int_pin:
|
---|
| 310 | mov dl, 3Ch
|
---|
| 311 | call pcibios_init_sel_reg
|
---|
[67668] | 312 | mov dx, PCI_CFG2 + 1 ; access config space at 3Dh
|
---|
[38699] | 313 | in al, dx
|
---|
| 314 | and al, 7
|
---|
| 315 | jz next_pci_func
|
---|
| 316 |
|
---|
| 317 | dec al ;; determine pirq reg
|
---|
| 318 | mov dl, 3
|
---|
| 319 | mul dl
|
---|
| 320 | add al, 2
|
---|
| 321 | xor ah, ah
|
---|
| 322 | mov bx, ax
|
---|
| 323 | mov al, [si+bx]
|
---|
| 324 | mov dl, al
|
---|
| 325 | mov bx, [bp]
|
---|
| 326 | call pcibios_init_sel_reg
|
---|
| 327 | mov dx, PCI_CFG2
|
---|
| 328 | and al, 3
|
---|
| 329 | add dl, al
|
---|
| 330 | in al, dx
|
---|
| 331 | cmp al, 80h
|
---|
| 332 | jb pirq_found
|
---|
| 333 |
|
---|
| 334 | mov bx, [bp-2] ;; pci irq list pointer
|
---|
| 335 | mov al, [bx]
|
---|
| 336 | out dx, al
|
---|
| 337 | inc bx
|
---|
| 338 | mov [bp-2], bx
|
---|
| 339 | call pcibios_init_set_elcr
|
---|
| 340 | pirq_found:
|
---|
| 341 | mov bh, [si]
|
---|
| 342 | mov bl, [si+1]
|
---|
| 343 | add bl, [bp-3] ;; pci function number
|
---|
| 344 | mov dl, 3Ch
|
---|
| 345 | call pcibios_init_sel_reg
|
---|
| 346 | mov dx, PCI_CFG2
|
---|
| 347 | out dx, al
|
---|
| 348 | next_pci_func:
|
---|
| 349 | inc byte ptr[bp-3]
|
---|
| 350 | inc bl
|
---|
| 351 | test bl, 7
|
---|
| 352 | jnz pci_init_irq_loop2
|
---|
| 353 |
|
---|
| 354 | next_pir_entry:
|
---|
| 355 | add si, 10h
|
---|
| 356 | mov byte ptr[bp-3], 0
|
---|
| 357 | loop pci_init_irq_loop1
|
---|
| 358 |
|
---|
| 359 | mov sp, bp
|
---|
| 360 | pop bx
|
---|
| 361 | pci_init_end:
|
---|
[67668] | 362 | endif
|
---|
[38699] | 363 | pop bp
|
---|
| 364 | pop ds
|
---|
| 365 | ret
|
---|
| 366 |
|
---|
| 367 | endif ; !BX_ROMBIOS32
|
---|
| 368 |
|
---|
| 369 | endif ; BX_PCIBIOS
|
---|
| 370 |
|
---|
[60422] | 371 | SET_DEFAULT_CPU_286
|
---|
| 372 |
|
---|